home *** CD-ROM | disk | FTP | other *** search
- /* tc-hppa.c -- Assemble for the PA
- Copyright (C) 1989 Free Software Foundation, Inc.
-
- This file is part of GAS, the GNU Assembler.
-
- GAS is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 1, or (at your option)
- any later version.
-
- GAS is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GAS; see the file COPYING. If not, write to
- the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
-
-
- /*
- HP PA-RISC support was contributed by the Center for Software Science
- at the University of Utah.
- */
-
- #include <stdio.h>
- #include <ctype.h>
-
- #include "as.h"
- #include "subsegs.h"
-
- /* #include "../bfd/libhppa.h" */
- /*
- * Unwind table and descriptor.
- */
-
- struct unwind_desc {
- unsigned int cannot_unwind : 1;
- unsigned int millicode : 1;
- unsigned int millicode_save_rest : 1;
- unsigned int region_desc : 2;
- unsigned int save_sr : 2;
- unsigned int entry_fr : 4; /* number saved */
- unsigned int entry_gr : 5; /* number saved */
- unsigned int args_stored : 1;
- unsigned int call_fr : 5;
- unsigned int call_gr : 5;
- unsigned int save_sp : 1;
- unsigned int save_rp : 1;
- unsigned int save_rp_in_frame : 1;
- unsigned int extn_ptr_defined : 1;
- unsigned int cleanup_defined : 1;
-
- unsigned int hpe_interrupt_marker : 1;
- unsigned int hpux_interrupt_marker : 1;
- unsigned int reserved : 3;
- unsigned int frame_size : 27;
- };
-
- typedef struct unwind_desc unwind_descS;
-
- struct unwind_table {
- unsigned int start_offset; /* starting offset (from SR4) of applicable region */
- unsigned int end_offset; /* ending offset (from SR4) of applicable region */
- unwind_descS descriptor;
- };
-
- typedef struct unwind_table unwind_tableS;
-
- /*
- * This structure is used by the .callinfo, .enter, .leave pseudo-ops to
- * control the entry and exit code they generate. It is also used in
- * creation of the correct stack unwind descriptors.
- *
- * The fields in structure roughly correspond to the arguments available on the
- * .callinfo pseudo-op.
- */
-
- struct call_info {
- int frame;
- int entry_sr;
- int makes_calls;
- int hpux_int;
- unwind_tableS ci_unwind; /* the unwind descriptor we are building */
- symbolS *start_symbol; /* name of function (used in relocation info) */
- symbolS *end_symbol; /* temporary symbol used to mark the */
- /* end of the function (used in */
- /* relocation info) */
- fragS *start_frag; /* frag associated w/ start of this function */
- fragS *end_frag; /* frag associated w/ end of this function */
- fragS *start_offset_frag; /* frag for start offset of this descriptor */
- int start_frag_where; /* where in start_offset_frag is start_offset */
- fixS *start_fix; /* fixup for the start_offset */
- fragS *end_offset_frag; /* frag for start offset of this descriptor */
- int end_frag_where; /* where in end_offset_frag is end_offset */
- fixS *end_fix; /* fixup for the end_offset */
- struct call_info *ci_next; /* the next call_info structure */
- };
-
- typedef struct call_info call_infoS;
-
- call_infoS *last_call_info;
- call_infoS *call_info_root;
- call_descS last_call_desc;
-
- /* A structure used during assembly of individual instructions */
-
- struct pa_it {
- char *error;
- unsigned long opcode;
- /* symbol_dictS *nlistp; *//*** used to be: struct nlist *nlistp; */
- asymbol * nlistp;
- expressionS exp;
- int pcrel;
- FP_Operand_Format fpof1; /* Floating Point Operand Format, operand 1 */
- FP_Operand_Format fpof2; /* Floating Point Operand Format, operand 2 */
- /* (used only for class 1 instructions -- */
- /* the conversion instructions) */
- #ifdef OBJ_SOM
- long field_selector;
- unsigned int reloc;
- int code;
- long arg_reloc;
- unwind_descS unwind;
- #endif
- #ifdef OBJ_ELF
- elf32_hppa_reloc_type reloc;
- long field_selector;
- int format;
- long arg_reloc;
- unwind_descS unwind;
- #endif
- };
-
- extern struct pa_it the_insn;
-
- /* careful, this file includes data *declarations* */
- #include "opcode/hppa.h"
-
- void md_begin();
- void md_end();
- void md_number_to_chars();
- void md_assemble();
- char *md_atof();
- void md_convert_frag();
- void md_create_short_jump();
- void md_create_long_jump();
- int md_estimate_size_before_relax();
- void md_number_to_imm();
- void md_number_to_disp();
- void md_number_to_field();
- void md_ri_to_chars();
- void emit_relocations();
- static void pa_ip();
-
-
- /* SKV 10/18/92. Added the following to assist in the determination of the
- relocation to be applied to an instruction. */
-
- #ifdef OBJ_ELF
-
- #define ERROR_INDICATOR -1
- #define ILLEGAL_RELOC ERROR_INDICATOR
-
- /* The following tables are indexed by [reloc_table_index(operand_format)] [field_selector]. */
-
- int HPPA_ADDR_RELOC_TABLE [N_HPPA_FIELD_SELECTORS] [N_HPPA_OPERAND_FORMATS] = {
- /* 11 12 14 17 21 */
- { R_HPPA_11, ILLEGAL_RELOC, R_HPPA_14, R_HPPA_17, ILLEGAL_RELOC}, /* F% */
- { ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, R_HPPA_L21}, /* L% */
- { R_HPPA_R11, ILLEGAL_RELOC, R_HPPA_R14, R_HPPA_R17, ILLEGAL_RELOC}, /* R% */
- { ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, R_HPPA_LS21}, /* LS% */
- { R_HPPA_RS11, ILLEGAL_RELOC, R_HPPA_RS14, R_HPPA_RS17, ILLEGAL_RELOC}, /* RS% */
- { ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, R_HPPA_LD21}, /* LD% */
- { R_HPPA_RD11, ILLEGAL_RELOC, R_HPPA_RD14, R_HPPA_RD17 ILLEGAL_RELOC}, /* RD% */
- { ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, R_HPPA_LR21}, /* LR% */
- { ILLEGAL_RELOC, ILLEGAL_RELOC, R_HPPA_RR14, R_HPPA_RR17, ILLEGAL_RELOC}, /* RR% */
- { ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC}, /* T% */
- { ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC}, /* LT% */
- { ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC}, /* RT% */
- { ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC}, /* P% */
- { ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC}, /* LP% */
- { ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC} /* RD */
- };
-
- int HPPA_GOTOFF_RELOC_TABLE [N_HPPA_FIELD_SELECTORS] [N_HPPA_OPERAND_FORMATS] = {
- /* 11 12 14 17 21 */
- { R_HPPA_GOTOFF_11, ILLEGAL_RELOC, R_HPPA_GOTOFF_14, ILLEGAL_RELOC, ILLEGAL_RELOC}, /* F% */
- { ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, R_HPPA_GOTOFF_L21}, /* L% */
- { R_HPPA_GOTOFF_R11, ILLEGAL_RELOC, R_HPPA_GOTOFF_R14, ILLEGAL_RELOC, ILLEGAL_RELOC}, /* R% */
- { ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, R_HPPA_GOTOFF_LS21}, /* LS% */
- { R_HPPA_GOTOFF_RS11, ILLEGAL_RELOC, R_HPPA_GOTOFF_RS14, ILLEGAL_RELOC, ILLEGAL_RELOC}, /* RS% */
- { ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, R_HPPA_GOTOFF_LD21}, /* LD% */
- { R_HPPA_GOTOFF_RD11, ILLEGAL_RELOC, R_HPPA_GOTOFF_RD14, ILLEGAL_RELOC, ILLEGAL_RELOC}, /* RD% */
- { ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, R_HPPA_GOTOFF_LR21}, /* LR% */
- { ILLEGAL_RELOC, ILLEGAL_RELOC, R_HPPA_GOTOFF_RR14, ILLEGAL_RELOC, ILLEGAL_RELOC}, /* RR% */
- { ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC}, /* T% */
- { ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC}, /* LT% */
- { ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC}, /* RT% */
- { ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC}, /* P% */
- { ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC}, /* LP% */
- { ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC} /* RP% */
- };
-
- int HPPA_ABS_CALL_RELOC_TABLE [N_HPPA_FIELD_SELECTORS] [N_HPPA_OPERAND_FORMATS] = {
- /* 11 12 14 17 21 */
- { R_HPPA_ABS_CALL_11, ILLEGAL_RELOC, R_HPPA_ABS_CALL_14, R_HPPA_ABS_CALL_17, ILLEGAL_RELOC}, /* F% */
- { ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, R_HPPA_ABS_CALL_L21}, /* L% */
- { R_HPPA_ABS_CALL_R11, ILLEGAL_RELOC, R_HPPA_ABS_CALL_R14, R_HPPA_ABS_CALL_R17, ILLEGAL_RELOC}, /* R% */
- { ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, R_HPPA_ABS_CALL_LS21}, /* LS% */
- { R_HPPA_ABS_CALL_RS11, ILLEGAL_RELOC, R_HPPA_ABS_CALL_RS14, R_HPPA_ABS_CALL_RS17, ILLEGAL_RELOC}, /* RS% */
- { ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, R_HPPA_ABS_CALL_LD21}, /* LD% */
- { R_HPPA_ABS_CALL_RD11, ILLEGAL_RELOC, R_HPPA_ABS_CALL_RD14, R_HPPA_ABS_CALL_RD17, ILLEGAL_RELOC}, /* RD% */
- { ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, R_HPPA_ABS_CALL_LR21}, /* LR% */
- { ILLEGAL_RELOC, ILLEGAL_RELOC, R_HPPA_ABS_CALL_RR14, R_HPPA_ABS_CALL_RR17, ILLEGAL_RELOC}, /* RR% */
- { ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC}, /* T% */
- { ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC}, /* LT% */
- { ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC}, /* RT% */
- { ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC}, /* P% */
- { ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC}, /* LP% */
- { ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC} /* RP% */
- };
-
- int HPPA_PCREL_CALL_RELOC_TABLE [N_HPPA_FIELD_SELECTORS] [N_HPPA_OPERAND_FORMATS] = {
- /* 11 12 14 17 21 */
- /* F% */
- { R_HPPA_PCREL_CALL_11, ILLEGAL_RELOC, R_HPPA_PCREL_CALL_14, R_HPPA_PCREL_CALL_17, ILLEGAL_RELOC},
- /* L% */
- { ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, R_HPPA_PCREL_CALL_L21},
- /* R% */
- { R_HPPA_PCREL_CALL_R11, ILLEGAL_RELOC, R_HPPA_PCREL_CALL_R14, R_HPPA_PCREL_CALL_R17, ILLEGAL_RELOC},
- /* LS% */
- { ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, R_HPPA_PCREL_CALL_LS21},
- /* RS% */
- { R_HPPA_PCREL_CALL_RS11, ILLEGAL_RELOC, R_HPPA_PCREL_CALL_RS14, R_HPPA_PCREL_CALL_RS17, ILLEGAL_RELOC},
- /* LD% */
- { ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, R_HPPA_PCREL_CALL_LD21},
- /* RD% */
- { R_HPPA_PCREL_CALL_RD11, ILLEGAL_RELOC, R_HPPA_PCREL_CALL_RD14, R_HPPA_PCREL_CALL_RD17, ILLEGAL_RELOC},
- /* LR% */
- { ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, R_HPPA_PCREL_CALL_LR21},
- /* RR% */
- { ILLEGAL_RELOC, ILLEGAL_RELOC, R_HPPA_PCREL_CALL_RR14, R_HPPA_PCREL_CALL_RR17, ILLEGAL_RELOC},
- /* T% */
- { ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC},
- /* LT% */
- { ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC},
- /* RT% */
- { ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC},
- /* P% */
- { ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC},
- /* LP% */
- { ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC},
- /* RP% */
- { ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC}
- };
-
- int HPPA_PLABEL_RELOC_TABLE [N_HPPA_FIELD_SELECTORS] [N_HPPA_OPERAND_FORMATS] = {
- /* 11 12 14 17 21 */
- { ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC}, /* F% */
- { ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC}, /* L% */
- { ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC}, /* R% */
- { ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC}, /* LS% */
- { ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC}, /* RS% */
- { ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC}, /* LD% */
- { ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC}, /* RD% */
- { ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC}, /* LR% */
- { ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC}, /* RR% */
- { ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC}, /* T% */
- { ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC}, /* LT% */
- { ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC}, /* RT% */
- { R_HPPA_PLABEL_11, ILLEGAL_RELOC, R_HPPA_PLABEL_14, ILLEGAL_RELOC, ILLEGAL_RELOC}, /* P% */
- { ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, ILLEGAL_RELOC, R_HPPA_PLABEL_L21}, /* LP% */
- { R_HPPA_PLABEL_R11, ILLEGAL_RELOC, R_HPPA_PLABEL_R14, ILLEGAL_RELOC, ILLEGAL_RELOC} /* RP% */
- };
-
-
- static int reloc_table_idx();
-
- #endif /* OBJ_ELF */
-
- const relax_typeS md_relax_table[] = { 0 };
- /* handle of the OPCODE hash table */
- static struct hash_control *op_hash = NULL;
-
- int md_short_jump_size = 4;
- int md_long_jump_size = 4;
-
- /* This array holds the chars that always start a comment. If the
- pre-processor is disabled, these aren't very useful */
- const char comment_chars[] = ";"; /* JF removed '|' from comment_chars */
-
- const pseudo_typeS
- md_pseudo_table[] = {
- { "align", s_align_bytes, 0 }, /* .align 4 means .align to 4-byte boundary */
- { "ALIGN", s_align_bytes, 0 }, /* .align 4 means .align to 4-byte boundary */
- { "block", pa_block, 1 },
- { "BLOCK", pa_block, 1 },
- { "blockz", pa_block, 0 },
- { "BLOCKZ", pa_block, 0 },
- { "call", pa_call, 0 },
- { "CALL", pa_call, 0 },
- { "callinfo", pa_callinfo, 0 },
- { "CALLINFO", pa_callinfo, 0 },
- { "code", pa_code, 0 },
- { "CODE", pa_code, 0 },
- { "comm", pa_comm, 0 },
- { "COMM", pa_comm, 0 },
- { "copyright",pa_copyright, 0 },
- { "COPYRIGHT",pa_copyright, 0 },
- { "end", pa_end, 0 },
- { "END", pa_end, 0 },
- { "enter", pa_enter, 0 },
- { "ENTER", pa_enter, 0 },
- { "entry", pa_entry, 0 },
- { "ENTRY", pa_entry, 0 },
- { "equ", pa_equ, 0 },
- { "EQU", pa_equ, 0 },
- { "exit", pa_exit, 0 },
- { "EXIT", pa_exit, 0 },
- { "export", pa_export, 0 },
- { "EXPORT", pa_export, 0 },
- { "half", cons, 2 },
- { "HALF", cons, 2 },
- { "import", pa_import, 0 },
- { "IMPORT", pa_import, 0 },
- { "label", pa_label, 0 },
- { "LABEL", pa_label, 0 },
- { "leave", pa_leave, 0 },
- { "LEAVE", pa_leave, 0 },
- { "origin", pa_origin, 0 },
- { "ORIGIN", pa_origin, 0 },
- { "proc", pa_proc, 0 },
- { "PROC", pa_proc, 0 },
- { "procend", pa_procend, 0 },
- { "PROCEND", pa_procend, 0 },
- { "reg", pa_equ, 1 }, /* very similar to .equ */
- { "REG", pa_equ, 1 }, /* very similar to .equ */
- { "space", pa_space, 0 },
- { "SPACE", pa_space, 0 },
- { "spnum", pa_spnum, 0 },
- { "SPNUM", pa_spnum, 0 },
- { "string", stringer, 0 },
- { "STRING", stringer, 0 },
- { "stringz", stringer, 1 },
- { "STRINGZ", stringer, 1 },
- { "subspa", pa_subspace, 0 },
- { "SUBSPA", pa_subspace, 0 },
- { "word", cons, 4 },
- { "WORD", cons, 4 },
- { NULL, 0, 0 }
- };
-
- /* This array holds the chars that only start a comment at the beginning of
- a line. If the line seems to have the form '# 123 filename'
- .line and .file directives will appear in the pre-processed output */
- /* Note that input_file.c hand checks for '#' at the beginning of the
- first line of the input file. This is because the compiler outputs
- #NO_APP at the beginning of its output. */
- /* Also note that '/*' will always start a comment */
- const char line_comment_chars[] = "#";
-
- const char line_separator_chars[] = "!";
-
- /* Chars that can be used to separate mant from exp in floating point nums */
- const char EXP_CHARS[] = "eE";
-
- /* Chars that mean this number is a floating point constant */
- /* As in 0f12.456 */
- /* or 0d1.2345e12 */
- const char FLT_CHARS[] = "rRsSfFdDxXpP";
-
- /* Also be aware that MAXIMUM_NUMBER_OF_CHARS_FOR_FLOAT may have to be
- changed in read.c . Ideally it shouldn't have to know about it at all,
- but nothing is ideal around here.
- */
-
- static unsigned char octal[256];
- #ifndef isoctal
- #define isoctal(c) octal[c]
- #endif
- static unsigned char toHex[256];
-
- struct pa_it set_insn; /* this structure is defined above */
-
- /* SKV 12/22/92. Added prev_insn, prev_fix, and initialized the_insn
- so that we can recognize instruction sequences such as (ldil, ble)
- and generate the appropriate fixups. */
-
- struct pa_it the_insn = {
- NULL, /* error */
- 0, /* opcode */
- NULL, /* nlistp */
- {
- NULL, /* exp.X_add_symbol */
- NULL, /* exp.X_subtract_symbol */
- 0, /* exp.X_add_number */
- NULL /* exp.asection */
- },
- 0, /* pcrel */
- 0, /* fpof1 */
- 0, /* fpof2 */
- 0, /* reloc */
- 0, /* field_selector */
- 0, /* code */
- 0, /* arg_reloc */
- { /* unwind */
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
- }
- };
-
- #ifdef OBJ_ELF
-
- struct pa_it prev_insn;
- char prev_str[10] = "";
- fixS *prev_fix = NULL;
- fixS *curr_fix = NULL;
-
- #endif /* OBJ_ELF */
-
- #ifdef __STDC__
- void print_insn(struct pa_it *insn);
- #else
- void print_insn();
- #endif
- char *expr_end;
-
- symbolS *label_symbolP; /* the last label symbol encountered */
- /* saved here in case a .equ is encountered */
- int label_symbol_defined;
-
- int callinfo_found; /* T if a .callinfo appeared within the current */
- /* procedure definition and F otherwise */
-
- int within_entry_exit; /* T if the assembler is currently within a */
- /* .entry/.exit pair and F otherwise */
-
- int exit_processing_complete; /* T is the assembler has completed exit */
- /* processing for the current procedure */
- /* and F otherwise */
-
- int within_procedure; /* T if the assembler is currently within a */
- /* a procedure definition and F otherwise */
-
- void ignore_rest_of_line(); /* a useful function in read.c */
-
- /* default space and subspace dictionaries */
-
- #define GDB_SYMBOLS GDB_SYMBOLS_SUBSPACE_NAME
- #define GDB_STRINGS GDB_STRINGS_SUBSPACE_NAME
-
- #if defined(OBJ_ELF)
- struct default_subspace_dict pa_def_subspaces[] =
- {
- { "$CODE$", 0, 1, 0, 0, 0, 0, 24, 0x2c, 0, 8, 0, 0, SUBSEG_CODE },
- { "$DATA$", 0, 1, 0, 0, 0, 0, 24, 0x1f, 0, 8, 1, 1, SUBSEG_DATA },
- { "$LIT$", 0, 1, 0, 0, 0, 0, 16, 0x2c, 0, 8, 0, 0, SUBSEG_LIT },
- { "$BSS$", 0, 1, 0, 0, 0, 1, 80, 0x1f, 0, 8, 1, 1, SUBSEG_BSS },
- { "$UNWIND$",0, 1, 0, 0, 0, 0, 64, 0x2c, 0, 4, 0, 0, SUBSEG_UNWIND },
- { GDB_STRINGS,0,0, 0, 0, 0, 0,254, 0x1f, 0, 4, 0, 2, SUBSEG_GDB_STRINGS },
- { GDB_SYMBOLS,0,0, 0, 0, 0, 0,255, 0x1f, 0, 4, 0, 2, SUBSEG_GDB_SYMBOLS },
- { NULL, 0, 1, 0, 0, 0, 0,255, 0x1f, 0, 4, 0, 0, 0 }
- };
-
- struct default_space_dict pa_def_spaces[] =
- {
- { "$TEXT$", 0, 1, 0, 0, 8, ASEC_NULL, ".text" },
- { "$PRIVATE$", 0, 1, 0, 0, 16, ASEC_NULL, ".data" },
- { GDB_DEBUG_SPACE_NAME, 0, 0, 0, 0, 255, ASEC_NULL, NULL /* ".debug" */ },
- { NULL, 0, 0, 0, 0, 0, ASEC_NULL, NULL }
- };
- #else
- struct default_subspace_dict pa_def_subspaces[] =
- {
- { "$CODE$", 0, 1, 0, 0, 0, 0, 24, 0x2c, 0, 8, 0, SEG_TEXT, SUBSEG_CODE },
- { "$DATA$", 0, 1, 0, 0, 0, 0, 24, 0x1f, 0, 8, 1, SEG_DATA, SUBSEG_DATA },
- { "$LIT$", 0, 1, 0, 0, 0, 0, 16, 0x2c, 0, 8, 0, SEG_TEXT, SUBSEG_LIT },
- { "$BSS$", 0, 1, 0, 0, 0, 1, 80, 0x1f, 0, 8, 1, SEG_DATA, SUBSEG_BSS },
- { "$UNWIND$",0, 1, 0, 0, 0, 0, 64, 0x2c, 0, 4, 0, SEG_TEXT, SUBSEG_UNWIND },
- { GDB_STRINGS,0,0, 0, 0, 0, 0,254, 0x1f, 0, 4, 0, SEG_GDB, SUBSEG_GDB_STRINGS
- },
- { GDB_SYMBOLS,0,0, 0, 0, 0, 0,255, 0x1f, 0, 4, 0, SEG_GDB, SUBSEG_GDB_SYMBOLS
- },
- { NULL,0,1,0,0,0,0,255,0x1f,0,4,0,SEG_GOOF,0 }
- };
-
- struct default_space_dict pa_def_spaces[] =
- {
- { "$TEXT$", 0, 1, 0, 0, 8, SEG_TEXT},
- { "$PRIVATE$", 0, 1, 0, 0, 16, SEG_DATA},
- { GDB_DEBUG_SPACE_NAME, 0, 0, 0, 0, 255, SEG_GDB},
- { NULL, 0, 0, 0, 0, 0, SEG_GOOF}
- };
- #endif
-
- #ifdef USG
- #define bcmp(b1,b2,n) memcmp((b1),(b2),(n))
- #define index strchr
- #endif
-
- #ifndef FALSE
- #define FALSE (0)
- #define TRUE (!FALSE)
- #endif /* no FALSE yet */
-
- /*
- Support for keeping track of the most recent label in each
- space.
- */
-
- /*
- PA_PSEUDO_OP_MOVES_PC
-
- A predicate that returns true if the pseudo-operation or
- assembly directive results in a movement in the current
- location. All instructions cause movement in the current
- location.
- */
-
- static const char * movers[] = {
- /* these entries from 'static pseudo_typeS potable[]' in pa-read.c */
- "ascii", "asciz",
- "byte",
- "comm",
- "data", "desc", "double",
- "fill", "float",
- "globl",
- "half",
- "int",
- "lcomm", "long", "lsym",
- "octa", "org",
- "quad",
- "short", "single",
- "text",
- "word",
- /* these entries from 'pseudo_typeS md_pseudo_table[]' in pa-aux.c */
- "block", "blockz",
- "code", "copyright",
- "equ",
- "origin",
- "reg", /* very similar to .equ */
- "string", "stringz",
- "version",
- NULL /* end sentinel */
- };
-
- int
- pa_pseudo_op_moves_pc(name)
- char * name;
- {
- int i = 0;
- while ( movers[i] ) {
- if ( strcmp(name,movers[i++]) == 0 )
- return 1;
- }
-
- return 0;
- }
-
- /*
- Support for keeping track of the most recent label in each
- space.
- */
-
- /* XXX: NOTE: label_symbolS is defined in pa.h */
-
- label_symbolS *label_symbols_rootP = NULL;
-
- /*
- PA_GET_LABEL
-
- Returns a pointer to the label_symbolS for the current space.
- */
-
- label_symbolS *
- pa_get_label()
- {
- label_symbolS *lssP;
- space_dict_chainS *now_sdcP = pa_segment_to_space(now_seg);
-
- for ( lssP = label_symbols_rootP; lssP; lssP = lssP->lss_next ) {
- if ( now_sdcP == lssP->lss_space && lssP->lss_label )
- return lssP;
- }
-
- return (label_symbolS *)NULL;
- }
-
- /*
- PA_LABEL_IS_DEFINED
-
- A predicate to determine whether a useable label is defined in
- the current space.
- */
-
- int
- pa_label_is_defined()
- {
- return (int)pa_get_label();
- }
-
- /*
- PA_DEFINE_LABEL
-
- Defines a label for the current space. If one is already defined,
- this function will replace it with the new label.
- */
-
- void
- pa_define_label(symbolP)
- symbolS * symbolP;
- {
- label_symbolS *lssP = pa_get_label();
- space_dict_chainS *now_sdcP = pa_segment_to_space(now_seg);
-
- if ( lssP ) {
- lssP->lss_label = symbolP;
- }
- else {
- lssP = (label_symbolS *)xmalloc(sizeof(label_symbolS));
- lssP->lss_label = symbolP;
- lssP->lss_space = now_sdcP;
- lssP->lss_next = (label_symbolS *)NULL;
-
- if ( label_symbols_rootP ) {
- lssP->lss_next = label_symbols_rootP;
- }
- label_symbols_rootP = lssP;
- }
- }
-
- /*
- PA_UNDEFINE_LABEL
-
- Removes a label definition for the current space.
- If there is no label_symbolS entry, then no action is taken.
- */
-
- void
- pa_undefine_label()
- {
- label_symbolS *lssP;
- label_symbolS *prevP = (label_symbolS *)NULL;
- space_dict_chainS *now_sdcP = pa_segment_to_space(now_seg);
-
- for ( lssP = label_symbols_rootP; lssP; lssP = lssP->lss_next ) {
- if ( now_sdcP == lssP->lss_space && lssP->lss_label ) {
- if ( prevP )
- prevP->lss_next = lssP->lss_next;
- else
- label_symbols_rootP = lssP->lss_next;
-
- free(lssP);
- break;
- }
- prevP = lssP;
- }
- }
-
- /* end of label symbol support. */
-
-
- /* An HPPA-specific version of fix_new. This is required because the HPPA */
- /* code needs to keep track of some extra stuff. Each call to fix_new_hppa */
- /* results in the creation of an instance of an hppa_fixS. An hppa_fixS */
- /* stores the extra information along with a pointer to the original fixS. */
-
- typedef struct hppa_fix_struct {
- fixS *fx_fixP;
- int fx_r_field;
- int fx_r_type;
- int fx_r_format;
- long fx_arg_reloc;
- call_infoS *fx_call_infop;
- char fx_unwind[8];
- struct hppa_fix_struct *fx_next;
- } hppa_fixS;
-
- hppa_fixS * hppa_fix_root = NULL;
-
- void fix_new_hppa(frag, where, size, add_symbol, sub_symbol, offset, pcrel,
- r_type, r_field, r_format, arg_reloc, unwind_desc)
- fragS *frag; /* Which frag? */
- int where; /* Where in that frag? */
- short int size; /* 1, 2 or 4 usually. */
- symbolS *add_symbol; /* X_add_symbol. */
- symbolS *sub_symbol; /* X_subtract_symbol. */
- long offset; /* X_add_number. */
- int pcrel; /* TRUE if PC-relative relocation. */
- enum reloc_type r_type; /* Relocation type */
- long r_field; /* F, R, L, etc */
- int r_format; /* 11,12,14,17,21,32, etc */
- long arg_reloc;
- char *unwind_desc;
- {
- fixS *new_fix = fix_new(frag, where, size,
- add_symbol, sub_symbol,
- offset, pcrel, r_type);
-
- hppa_fixS *hppa_fix = (hppa_fixS *)obstack_alloc(¬es,sizeof(hppa_fixS));
-
- hppa_fix->fx_fixP = new_fix;
- hppa_fix->fx_r_field = r_field;
- hppa_fix->fx_r_format = r_format;
- hppa_fix->fx_arg_reloc = arg_reloc;
- hppa_fix->fx_next = (hppa_fixS *)0;
- hppa_fix->fx_call_infop = last_call_info;
- if (unwind_desc)
- bcopy(unwind_desc, hppa_fix->fx_unwind, 8);
-
- if ( hppa_fix_root )
- hppa_fix->fx_next = hppa_fix_root;
-
- hppa_fix_root = hppa_fix;
-
- /* SKV 12/22/92. Added prev_insn, prev_fix, and initialized the_insn
- so that we can recognize instruction sequences such as (ldil, ble)
- and generate the appropriate fixups. */
-
- #ifdef OBJ_ELF
-
- curr_fix = new_fix;
-
- #endif /* OBJ_ELF */
- }
-
- /* Given a FixS, find the hppa_fixS associated with it. */
- hppa_fixS *
- hppa_find_hppa_fix(fix)
- fixS *fix;
- {
- hppa_fixS *hfP;
-
- for ( hfP = hppa_fix_root; hfP; hfP = hfP->fx_next ) {
- if ( hfP->fx_fixP == fix )
- return hfP;
- }
-
- return (hppa_fixS *)0;
- }
-
- /* This function is called once, at assembler startup time. It should
- set up all the tables, etc. that the MD part of the assembler will need. */
- void
- md_begin()
- {
- register char *retval = NULL;
- int lose = 0;
- register unsigned int i = 0;
-
- last_call_info = NULL;
- call_info_root = NULL;
-
- pa_spaces_begin();
-
- op_hash = hash_new();
- if (op_hash == NULL)
- as_fatal("Virtual memory exhausted");
-
- while (i < NUMOPCODES)
- {
- const char *name = pa_opcodes[i].name;
- retval = hash_insert(op_hash, name, &pa_opcodes[i]);
- if(retval != NULL && *retval != '\0')
- {
- as_fatal("Internal error: can't hash `%s': %s\n",
- pa_opcodes[i].name, retval);
- lose = 1;
- }
- do
- {
- if ( (pa_opcodes[i].match & pa_opcodes[i].mask) != pa_opcodes[i].match )
- {
- fprintf(stderr, "internal error: losing opcode: `%s' \"%s\"\n",
- pa_opcodes[i].name, pa_opcodes[i].args);
- lose = 1;
- }
- ++i;
- } while (i < NUMOPCODES
- && !strcmp(pa_opcodes[i].name, name));
- }
-
- if (lose)
- as_fatal ("Broken assembler. No assembly attempted.");
-
- for (i = '0'; i < '8'; ++i)
- octal[i] = 1;
- for (i = '0'; i <= '9'; ++i)
- toHex[i] = i - '0';
- for (i = 'a'; i <= 'f'; ++i)
- toHex[i] = i + 10 - 'a';
- for (i = 'A'; i <= 'F'; ++i)
- toHex[i] = i + 10 - 'A';
-
- }
-
- void
- md_end()
- {
- return;
- }
-
- void
- md_assemble(str)
- char *str;
- {
- char *toP;
-
- assert(str);
- pa_ip(str);
- toP = frag_more(4);
- /* put out the opcode */
- md_number_to_chars(toP, the_insn.opcode, 4);
-
- /* put out the symbol-dependent stuff */
- #if defined ( OBJ_SOM )
- if (the_insn.reloc != R_NO_RELOCATION) {
- #elif defined ( OBJ_ELF )
- if (the_insn.reloc != R_HPPA_NONE) {
- #endif
-
- #if defined(OBJ_ELF)
- fix_new_hppa(frag_now, /* which frag */
- (toP - frag_now->fr_literal), /* where */
- 4, /* size */
- the_insn.exp.X_add_symbol,
- the_insn.exp.X_subtract_symbol,
- the_insn.exp.X_add_number,
- the_insn.pcrel,
- the_insn.reloc,
- the_insn.field_selector,
- the_insn.format,
- the_insn.arg_reloc,
- (char *) 0 );
- #endif
- #ifdef OBJ_SOM
- fix_new(frag_now, /* which frag */
- (toP - frag_now->fr_literal), /* where */
- 4, /* size */
- the_insn.exp.X_add_symbol,
- the_insn.exp.X_subtract_symbol,
- the_insn.exp.X_add_number,
- the_insn.pcrel,
- the_insn.reloc,
- the_insn.field_selector,
- the_insn.code,
- the_insn.arg_reloc,
- (char *) 0 );
- #endif
- }
-
- /* SKV 12/22/92. Added prev_insn, prev_fix, and initialized the_insn
- so that we can recognize instruction sequences such as (ldil, ble)
- and generate the appropriate fixups. */
-
- #ifdef OBJ_ELF
-
- prev_insn = the_insn;
- strncpy(prev_str, str, 10);
- if (prev_insn.reloc = R_HPPA_NONE)
- {
- prev_fix = NULL;
- }
- else
- {
- prev_fix = curr_fix;
- }
-
- #endif /* OBJ_ELF */
- }
-
- static void
- pa_ip(str)
- char *str;
- {
- char *error_message = "";
- char *s;
- const char *args;
- char c;
- unsigned long i;
- struct pa_opcode *insn;
- char *argsStart;
- unsigned long opcode;
- unsigned int mask;
- int match = FALSE;
- int comma = 0;
-
- int reg,reg1,reg2,s2,s3;
- unsigned int im21,im14,im11,im5;
- int m,a,uu,f;
- int cmpltr,nullif, flag;
- int sfu, cond;
- char *name;
- char *p, *save_s;
-
- #ifdef PA_DEBUG
- fprintf(stderr,"STATEMENT: \"%s\"\n",str);
- #endif
- for (s = str; isupper(*s) || islower(*s) || (*s >= '0' && *s <= '3'); ++s)
- ;
- switch (*s) {
-
- case '\0':
- break;
-
- case ',':
- comma = 1;
-
- /*FALLTHROUGH*/
-
- case ' ':
- *s++ = '\0';
- break;
-
- default:
- as_bad("Unknown opcode: `%s'", str);
- exit(1);
- }
-
- save_s = str;
-
- while ( *save_s ) {
- if ( isupper(*save_s) )
- *save_s = tolower(*save_s);
- save_s++;
- }
-
- if ((insn = (struct pa_opcode *) hash_find(op_hash, str)) == NULL) {
- as_bad("Unknown opcode: `%s'", str);
- return;
- }
- if (comma) {
- *--s = ',';
- }
- argsStart = s;
- for (;;) {
- opcode = insn->match;
- bzero(&the_insn, sizeof(the_insn));
- #if defined( OBJ_SOM )
- the_insn.reloc = R_NO_RELOCATION;
- #else
- #if defined ( OBJ_ELF )
- the_insn.reloc = R_HPPA_NONE;
- #endif
- #endif
- /*
- * Build the opcode, checking as we go to make
- * sure that the operands match
- */
- for (args = insn->args; ; ++args) {
-
- switch (*args) {
-
- case '\0': /* end of args */
- if (*s == '\0') {
- match = TRUE;
- }
- break;
-
- case '+':
- if (*s == '+') {
- ++s;
- continue;
- }
- if (*s == '-') {
- continue;
- }
- break;
-
- case '(': /* these must match exactly */
- case ')':
- case ',':
- case ' ':
- if (*s++ == *args)
- continue;
- break;
-
- case 'b': /* 5 bit register field at 10 */
- case '^': /* 5 bit control register field at 10 */
- reg = pa_parse_number(&s);
- if ( reg < 32 && reg >= 0 ) {
- opcode |= reg << 21;
- continue;
- }
- break;
- case 'x': /* 5 bit register field at 15 */
- reg = pa_parse_number(&s);
- if ( reg < 32 && reg >= 0 ) {
- opcode |= reg << 16;
- continue;
- }
- break;
- case 't': /* 5 bit register field at 31 */
- reg = pa_parse_number(&s);
- if ( reg < 32 && reg >= 0 ) {
- opcode |= reg;
- continue;
- }
- break;
- case 'T': /* 5 bit field length at 31 (encoded as 32-T) */
- /*
- reg = pa_parse_number(&s);
- */
- getAbsoluteExpression(s);
- if ( the_insn.exp.X_seg == &bfd_abs_section ) {
- reg = the_insn.exp.X_add_number;
- if ( reg <= 32 && reg > 0 ) {
- opcode |= 32 - reg;
- s = expr_end;
- continue;
- }
- }
- break;
- case '5': /* 5 bit immediate at 15 */
- getAbsoluteExpression(s);
- /** PJH: The following 2 calls to as_bad() might eventually **/
- /** want to end up as as_warn(). **/
- if ( the_insn.exp.X_add_number > 15 ) {
- as_bad("5 bit immediate > 15. Set to 15",
- the_insn.exp.X_add_number);
- the_insn.exp.X_add_number = 15;
- }
- else if ( the_insn.exp.X_add_number < -16 ) {
- as_bad("5 bit immediate < -16. Set to -16",
- the_insn.exp.X_add_number);
- the_insn.exp.X_add_number = -16;
- }
-
- low_sign_unext(evaluateAbsolute(the_insn.exp,the_insn.field_selector),
- 5,&im5);
- opcode |= ( im5 << 16 );
- s = expr_end;
- continue;
-
- case 's': /* 2 bit space identifier at 17 */
- s2 = pa_parse_number(&s);
- if ( s2 < 4 && s2 >= 0 ) {
- opcode |= s2 << 14;
- continue;
- }
- break;
- case 'S': /* 3 bit space identifier at 18 */
- s3 = pa_parse_number(&s);
- if ( s3 < 8 && s3 >= 0 ) {
- dis_assemble_3(s3,&s3);
- opcode |= s3 << 13;
- continue;
- }
- break;
- case 'c': /* indexed load completer. */
- uu = 0;
- m = 0;
- i = 0;
- while ( *s == ',' && i < 2 ) {
- s++;
- if ( strncasecmp(s,"sm",2) == 0 ) {
- uu = 1;
- m = 1;
- s++;
- i++;
- }
- else if ( strncasecmp(s,"m",1) == 0 )
- m = 1;
- else if ( strncasecmp(s,"s",1) == 0 )
- uu = 1;
- else
- as_bad("Unrecognized Indexed Load Completer...assuming 0");
- s++;
- i++;
- }
- if ( i > 2 )
- as_bad("Illegal Indexed Load Completer Syntax...extras ignored");
- /* pa_skip(&s); */
- while ( *s == ' ' || *s == '\t' )
- s++;
-
- opcode |= m << 5;
- opcode |= uu << 13;
- continue;
- case 'C': /* short load and store completer */
- a = 0;
- m = 0;
- if ( *s == ',' ) {
- s++;
- if ( strncasecmp(s,"ma",2) == 0 ) {
- a = 0;
- m = 1;
- }
- else if ( strncasecmp(s,"mb",2) == 0 ) {
- a = 1;
- m = 1;
- }
- else
- as_bad("Unrecognized Indexed Load Completer...assuming 0");
- s += 2;
- }
- /* pa_skip(&s); */
- while ( *s == ' ' || *s == '\t' )
- s++;
- opcode |= m << 5;
- opcode |= a << 13;
- continue;
- case 'Y': /* Store Bytes Short completer */
- a = 0;
- m = 0;
- i = 0;
- while ( *s == ',' && i < 2 ) {
- s++;
- if ( strncasecmp(s,"m",1) == 0 )
- m = 1;
- else if ( strncasecmp(s,"b",1) == 0 )
- a = 0;
- else if ( strncasecmp(s,"e",1) == 0 )
- a = 1;
- else
- as_bad("Unrecognized Store Bytes Short Completer...assuming 0");
- s++;
- i++;
- }
- /** if ( i >= 2 ) **/
- if ( i > 2 )
- as_bad("Illegal Store Bytes Short Completer...extras ignored");
- while ( *s == ' ' || *s == '\t' ) /* skip to next operand */
- s++;
- opcode |= m << 5;
- opcode |= a << 13;
- continue;
- case '<': /* non-negated compare/subtract conditions. */
- cmpltr = pa_parse_nonneg_cmpsub_cmpltr(&s);
- if ( cmpltr < 0 ) {
- as_bad("Unrecognized Compare/Subtract Condition: %c",*s);
- cmpltr = 0;
- }
- opcode |= cmpltr << 13;
- continue;
- case '?': /* negated or non-negated cmp/sub conditions. */
- /* used only by ``comb'' and ``comib'' pseudo-ops */
- save_s = s;
- cmpltr = pa_parse_nonneg_cmpsub_cmpltr(&s);
- if ( cmpltr < 0 ) {
- s = save_s;
- cmpltr = pa_parse_neg_cmpsub_cmpltr(&s);
- if ( cmpltr < 0 ) {
- as_bad("Unrecognized Compare/Subtract Condition: %c",*s);
- cmpltr = 0;
- }
- else {
- opcode |= 1 << 27; /* required opcode change to make
- COMIBT into a COMIBF or a
- COMBT into a COMBF or a
- ADDBT into a ADDBF or a
- ADDIBT into a ADDIBF */
- }
- }
- opcode |= cmpltr << 13;
- continue;
- case '!': /* negated or non-negated add conditions. */
- /* used only by ``addb'' and ``addib'' pseudo-ops */
- save_s = s;
- cmpltr = pa_parse_nonneg_add_cmpltr(&s);
- if ( cmpltr < 0 ) {
- s = save_s;
- cmpltr = pa_parse_neg_add_cmpltr(&s);
- if ( cmpltr < 0 ) {
- as_bad("Unrecognized Compare/Subtract Condition: %c",*s);
- cmpltr = 0;
- }
- else {
- opcode |= 1 << 27; /* required opcode change to make
- COMIBT into a COMIBF or a
- COMBT into a COMBF or a
- ADDBT into a ADDBF or a
- ADDIBT into a ADDIBF */
- }
- }
- opcode |= cmpltr << 13;
- continue;
- case 'a': /* compare/subtract conditions */
- cmpltr = 0;
- f = 0;
- save_s = s;
- if ( *s == ',' ) {
- cmpltr = pa_parse_nonneg_cmpsub_cmpltr(&s);
- if ( cmpltr < 0 ) {
- f = 1;
- s = save_s;
- cmpltr = pa_parse_neg_cmpsub_cmpltr(&s);
- if ( cmpltr < 0 ) {
- as_bad("Unrecognized Compare/Subtract Condition");
- }
- }
- }
- opcode |= cmpltr << 13;
- opcode |= f << 12;
- continue;
- case 'd': /* non-negated add conditions */
- cmpltr = 0;
- nullif = 0;
- flag = 0;
- if ( *s == ',' ) {
- s++;
- name = s;
- while ( *s != ',' && *s != ' ' && *s != '\t' )
- s += 1;
- c = *s;
- *s = 0x00;
- if ( strcmp(name,"=") == 0 ) {
- cmpltr = 1;
- }
- else if ( strcmp(name,"<") == 0 ) {
- cmpltr = 2;
- }
- else if ( strcmp(name,"<=") == 0 ) {
- cmpltr = 3;
- }
- else if ( strcasecmp(name,"nuv") == 0 ) {
- cmpltr = 4;
- }
- else if ( strcasecmp(name,"znv") == 0 ) {
- cmpltr = 5;
- }
- else if ( strcasecmp(name,"sv") == 0 ) {
- cmpltr = 6;
- }
- else if ( strcasecmp(name,"od") == 0 ) {
- cmpltr = 7;
- }
- else if ( strcasecmp(name,"n") == 0 ) {
- nullif = 1;
- }
- else if ( strcasecmp(name,"tr") == 0 ) {
- cmpltr = 0;
- flag = 1;
- }
- else if ( strcasecmp(name,"<>") == 0 ) {
- cmpltr = 1;
- flag = 1;
- }
- else if ( strcasecmp(name,">=") == 0 ) {
- cmpltr = 2;
- flag = 1;
- }
- else if ( strcasecmp(name,">") == 0 ) {
- cmpltr = 3;
- flag = 1;
- }
- else if ( strcasecmp(name,"uv") == 0 ) {
- cmpltr = 4;
- flag = 1;
- }
- else if ( strcasecmp(name,"vnz") == 0 ) {
- cmpltr = 5;
- flag = 1;
- }
- else if ( strcasecmp(name,"nsv") == 0 ) {
- cmpltr = 6;
- flag = 1;
- }
- else if ( strcasecmp(name,"ev") == 0 ) {
- cmpltr = 7;
- flag = 1;
- }
- else
- as_bad("Unrecognized Add Condition: %s",name);
- *s = c;
- }
- nullif = pa_parse_nullif(&s);
- opcode |= nullif << 1;
- opcode |= cmpltr << 13;
- opcode |= flag << 12;
- continue;
- case '&': /* logical instruction conditions */
- cmpltr = 0;
- f = 0;
- if ( *s == ',' ) {
- s++;
- name = s;
- while ( *s != ',' && *s != ' ' && *s != '\t' )
- s += 1;
- c = *s;
- *s = 0x00;
- if ( strcmp(name,"=") == 0 ) {
- cmpltr = 1;
- }
- else if ( strcmp(name,"<") == 0 ) {
- cmpltr = 2;
- }
- else if ( strcmp(name,"<=") == 0 ) {
- cmpltr = 3;
- }
- else if ( strcasecmp(name,"od") == 0 ) {
- cmpltr = 7;
- }
- else if ( strcasecmp(name,"tr") == 0 ) {
- cmpltr = 0;
- f = 1;
- }
- else if ( strcmp(name,"<>") == 0 ) {
- cmpltr = 1;
- f = 1;
- }
- else if ( strcmp(name,">=") == 0 ) {
- cmpltr = 2;
- f = 1;
- }
- else if ( strcmp(name,">") == 0 ) {
- cmpltr = 3;
- f = 1;
- }
- else if ( strcasecmp(name,"ev") == 0 ) {
- cmpltr = 7;
- f = 1;
- }
- else
- as_bad("Unrecognized Logical Instruction Condition: %s",name);
- *s = c;
- }
- opcode |= cmpltr << 13;
- opcode |= f << 12;
- continue;
- case 'U': /* unit instruction conditions */
- cmpltr = 0;
- f = 0;
- if ( *s == ',' ) {
- s++;
- if ( strncasecmp(s,"sbz",3) == 0 ) {
- cmpltr = 2;
- s += 3;
- }
- else if ( strncasecmp(s,"shz",3) == 0 ) {
- cmpltr = 3;
- s += 3;
- }
- else if ( strncasecmp(s,"sdc",3) == 0 ) {
- cmpltr = 4;
- s += 3;
- }
- else if ( strncasecmp(s,"sbc",3) == 0 ) {
- cmpltr = 6;
- s += 3;
- }
- else if ( strncasecmp(s,"shc",3) == 0 ) {
- cmpltr = 7;
- s += 3;
- }
- else if ( strncasecmp(s,"tr",2) == 0 ) {
- cmpltr = 0;
- f = 1;
- s += 2;
- }
- else if ( strncasecmp(s,"nbz",3) == 0 ) {
- cmpltr = 2;
- f = 1;
- s += 3;
- }
- else if ( strncasecmp(s,"nhz",3) == 0 ) {
- cmpltr = 3;
- f = 1;
- s += 3;
- }
- else if ( strncasecmp(s,"ndc",3) == 0 ) {
- cmpltr = 4;
- f = 1;
- s += 3;
- }
- else if ( strncasecmp(s,"nbc",3) == 0 ) {
- cmpltr = 6;
- f = 1;
- s += 3;
- }
- else if ( strncasecmp(s,"nhc",3) == 0 ) {
- cmpltr = 7;
- f = 1;
- s += 3;
- }
- else
- as_bad("Unrecognized Logical Instruction Condition: %c",*s);
- }
- opcode |= cmpltr << 13;
- opcode |= f << 12;
- continue;
- case '>': /* shift/extract/deposit conditions. */
- cmpltr = 0;
- if ( *s == ',' ) {
- s++;
- name = s;
- while ( *s != ',' && *s != ' ' && *s != '\t' )
- s += 1;
- c = *s;
- *s = 0x00;
- if ( strcmp(name,"=") == 0 ) {
- cmpltr = 1;
- }
- else if ( strcmp(name,"<") == 0 ) {
- cmpltr = 2;
- }
- else if ( strcasecmp(name,"od") == 0 ) {
- cmpltr = 3;
- }
- else if ( strcasecmp(name,"tr") == 0 ) {
- cmpltr = 4;
- }
- else if ( strcmp(name,"<>") == 0 ) {
- cmpltr = 5;
- }
- else if ( strcmp(name,">=") == 0 ) {
- cmpltr = 6;
- }
- else if ( strcasecmp(name,"ev") == 0 ) {
- cmpltr = 7;
- }
- else
- as_bad("Unrecognized Shift/Extract/Deposit Condition: %s",name);
- *s = c;
- }
- opcode |= cmpltr << 13;
- continue;
- case '~': /* bvb,bb conditions */
- cmpltr = 0;
- if ( *s == ',' ) {
- s++;
- if ( strncmp(s,"<",1) == 0 ) {
- cmpltr = 2;
- s++;
- }
- else if ( strncmp(s,">=",2) == 0 ) {
- cmpltr = 6;
- s += 2;
- }
- else
- as_bad("Unrecognized Bit Branch Condition: %c",*s);
- }
- opcode |= cmpltr << 13;
- continue;
- case 'V': /* 5 bit immediate at 31 */
- getExpression(s);
- low_sign_unext(evaluateAbsolute(the_insn.exp,the_insn.field_selector),
- 5,&im5);
- opcode |= im5;
- s = expr_end;
- continue;
- case 'r': /* 5 bit immediate at 31 */
- /* (unsigned value for the break instruction) */
- getExpression(s);
- im5 = evaluateAbsolute(the_insn.exp,the_insn.field_selector);
- if ( im5 > 31 || im5 < 0 ) {
- as_bad("Operand out of range. Was: %d. Should be [0..31]. Assuming %d.\n",im5,im5&0x1f);
- im5 = im5 & 0x1f;
- }
- opcode |= im5;
- s = expr_end;
- continue;
- case 'R': /* 5 bit immediate at 15 */
- /* (unsigned value for the ssm and rsm instruction) */
- getExpression(s);
- im5 = evaluateAbsolute(the_insn.exp,the_insn.field_selector);
- if ( im5 > 31 || im5 < 0 ) {
- as_bad("Operand out of range. Was: %d. Should be [0..31]. Assuming %d.\n",im5,im5&0x1f);
- im5 = im5 & 0x1f;
- }
- opcode |= im5 << 16;
- s = expr_end;
- continue;
- case 'i': /* 11 bit immediate at 31 */
- #ifdef OBJ_SOM
- getExpression(s);
- if ( the_insn.exp.X_seg == &bfd_abs_section ) {
- low_sign_unext(evaluateAbsolute(the_insn.exp,the_insn.field_selector),
- 11,&im11);
- opcode |= im11;
- }
- else {
- the_insn.reloc = R_CODE_ONE_SYMBOL;
- the_insn.code = 'i';
- the_insn.field_selector = the_insn.exp.field_selector;
- }
- s = expr_end;
- continue;
- #else
- the_insn.field_selector = pa_chk_field_selector(&s);
- getExpression(s);
- if ( the_insn.exp.X_seg == &bfd_abs_section ) {
- low_sign_unext(evaluateAbsolute(the_insn.exp,the_insn.field_selector),
- 11,&im11);
- opcode |= im11;
- }
- else {
- if ( is_DP_relative(the_insn.exp) )
- the_insn.reloc = R_HPPA_GOTOFF;
- else
- the_insn.reloc = R_HPPA;
- the_insn.format = 11;
- }
- s = expr_end;
- continue;
- #endif
- case 'j': /* 14 bit immediate at 31 */
- #ifdef OBJ_SOM
- getExpression(s);
- if ( the_insn.exp.X_seg == &bfd_abs_section ) {
- low_sign_unext(evaluateAbsolute(the_insn.exp,field_selector),
- 14,&im14);
- if ( the_insn.exp.field_selector == e_rsel )
- opcode |= (im14 & 0xfff);
- else
- opcode |= im14;
- }
- else {
- the_insn.reloc = R_CODE_ONE_SYMBOL;
- the_insn.code = 'j';
- the_insn.field_selector = the_insn.exp.field_selector;
- }
- s = expr_end;
- continue;
- #else
- the_insn.field_selector = pa_chk_field_selector(&s);
- getExpression(s);
- if ( the_insn.exp.X_seg == &bfd_abs_section ) {
- low_sign_unext(evaluateAbsolute(the_insn.exp,the_insn.field_selector),
- 14,&im14);
- if ( the_insn.field_selector == e_rsel )
- opcode |= (im14 & 0xfff);
- else
- opcode |= im14;
- }
- else {
- if ( is_DP_relative(the_insn.exp) )
- the_insn.reloc = R_HPPA_GOTOFF;
- else
- the_insn.reloc = R_HPPA;
- the_insn.format = 14;
- }
- s = expr_end;
- continue;
- #endif
-
- case 'k': /* 21 bit immediate at 31 */
- #ifdef OBJ_SOM
- getExpression(s);
- if ( the_insn.exp.X_seg == &bfd_abs_section ) {
- dis_assemble_21(evaluateAbsolute(the_insn.exp,the_insn.field_selector),
- &im21);
- opcode |= im21;
- }
- else {
- the_insn.reloc = R_CODE_ONE_SYMBOL;
- the_insn.code = 'k';
- the_insn.field_selector = the_insn.exp.field_selector;
- }
- s = expr_end;
- continue;
- #else
- the_insn.field_selector = pa_chk_field_selector(&s);
- getExpression(s);
- if ( the_insn.exp.X_seg == &bfd_abs_section ) {
- dis_assemble_21(evaluateAbsolute(the_insn.exp,the_insn.field_selector),
- &im21);
- opcode |= im21;
- }
- else {
- if ( is_DP_relative(the_insn.exp) )
- the_insn.reloc = R_HPPA_GOTOFF;
- else
- the_insn.reloc = R_HPPA;
- the_insn.format = 21;
- }
- s = expr_end;
- continue;
- #endif
-
- case 'n': /* nullification for branch instructions */
- nullif = pa_parse_nullif(&s);
- opcode |= nullif << 1;
- continue;
- case 'w': /* 12 bit branch displacement */
- #ifdef OBJ_SOM
- getExpression(s);
- the_insn.pcrel = 1;
- if ( strcmp(the_insn.exp.X_add_symbol->sy_nlist.n_un.n_name,"L0\001") == 0 ) {
- unsigned int w1,w,result;
-
- sign_unext( (the_insn.exp.X_add_number - 8) >> 2,12,&result);
- dis_assemble_12(result,&w1,&w);
- opcode |= ( ( w1 << 2 ) | w );
- the_insn.exp.X_add_symbol->sy_ref = FALSE;
- }
- else {
- /* this has to be wrong -- dont know what is right! */
- the_insn.reloc = R_PCREL_CALL;
- the_insn.code = 'w';
- the_insn.field_selector = the_insn.exp.field_selector;
- the_insn.arg_reloc = last_call_desc.arg_reloc;
- bzero(&last_call_desc,sizeof(call_descS));
- }
- s = expr_end;
- continue;
- #else
- the_insn.field_selector = pa_chk_field_selector(&s);
- getExpression(s);
- the_insn.pcrel = 1;
- if ( strcmp(S_GET_NAME(the_insn.exp.X_add_symbol),"L0\001") == 0 ) {
- unsigned int w1,w,result;
-
- sign_unext( (the_insn.exp.X_add_number - 8) >> 2,12,&result);
- dis_assemble_12(result,&w1,&w);
- opcode |= ( ( w1 << 2 ) | w );
- /* the_insn.exp.X_add_symbol->sy_ref = FALSE; */ /* XXX: not sure how to do this in BFD */
- }
- else {
- /* this has to be wrong -- dont know what is right! */
- the_insn.reloc = R_HPPA_PCREL_CALL;
- the_insn.format = 12;
- the_insn.arg_reloc = last_call_desc.arg_reloc;
- bzero(&last_call_desc,sizeof(call_descS));
- }
- s = expr_end;
- continue;
- #endif
- case 'W': /* 17 bit branch displacement */
- #if defined(OBJ_ELF)
- the_insn.field_selector = pa_chk_field_selector(&s);
- #endif
- getExpression(s);
- the_insn.pcrel = 1;
- #ifdef OBJ_SOM
- if ( strcmp(the_insn.exp.X_add_symbol->sy_nlist.n_un.n_name,"L0\001") == 0 ) {
- unsigned int w2,w1,w,result;
-
- sign_unext( (the_insn.exp.X_add_number - 8) >> 2,17,&result);
- dis_assemble_17(result,&w1,&w2,&w);
- opcode |= ( ( w2 << 2 ) | ( w1 << 16 ) | w );
- the_insn.exp.X_add_symbol->sy_ref = FALSE;
- }
- else {
- /* this has to be wrong -- dont know what is right! */
- the_insn.reloc = R_PCREL_CALL;
- the_insn.code = 'W';
- the_insn.field_selector = the_insn.exp.field_selector;
- the_insn.arg_reloc = last_call_desc.arg_reloc;
- bzero(&last_call_desc,sizeof(call_descS));
- }
- #else
- if ( the_insn.exp.X_add_symbol ) {
- if ( strcmp(S_GET_NAME(the_insn.exp.X_add_symbol),"L0\001") == 0 ) {
- unsigned int w2,w1,w,result;
-
- sign_unext( (the_insn.exp.X_add_number - 8) >> 2,17,&result);
- dis_assemble_17(result,&w1,&w2,&w);
- opcode |= ( ( w2 << 2 ) | ( w1 << 16 ) | w );
- }
- else {
- /* this has to be wrong -- dont know what is right! */
- the_insn.reloc = R_HPPA_PCREL_CALL;
- the_insn.format = 17;
- the_insn.arg_reloc = last_call_desc.arg_reloc;
- bzero(&last_call_desc,sizeof(call_descS));
- }
- }
- else {
- unsigned int w2,w1,w,result;
-
- sign_unext( the_insn.exp.X_add_number >> 2,17,&result);
- dis_assemble_17(result,&w1,&w2,&w);
- opcode |= ( ( w2 << 2 ) | ( w1 << 16 ) | w );
- }
- #endif
- s = expr_end;
- continue;
- case 'p': /* 5 bit shift count at 26 (to support SHD instr.) */
- /* value is encoded in instr. as 31-p where p is */
- /* the value scanned here */
- getExpression(s);
- if ( the_insn.exp.X_seg == &bfd_abs_section ) {
- opcode |= ( ( (31 - the_insn.exp.X_add_number) & 0x1f ) << 5 );
- }
- s = expr_end;
- continue;
- case 'P': /* 5-bit bit position at 26 */
- getExpression(s);
- if ( the_insn.exp.X_seg == &bfd_abs_section ) {
- opcode |= ( the_insn.exp.X_add_number & 0x1f ) << 5;
- }
- s = expr_end;
- continue;
- case 'Q': /* 5 bit immediate at 10 */
- /* (unsigned bit position value for the bb instruction) */
- getExpression(s);
- im5 = evaluateAbsolute(the_insn.exp,the_insn.field_selector);
- if ( im5 > 31 || im5 < 0 ) {
- as_bad("Operand out of range. Was: %d. Should be [0..31]. Assuming %d.\n",im5,im5&0x1f);
- im5 = im5 & 0x1f;
- }
- opcode |= im5 << 21;
- s = expr_end;
- continue;
- case 'A': /* 13 bit immediate at 18 (to support BREAK instr.) */
- getAbsoluteExpression(s);
- if ( the_insn.exp.X_seg == &bfd_abs_section )
- opcode |= (the_insn.exp.X_add_number & 0x1fff) << 13;
- s = expr_end;
- continue;
- case 'Z': /* System Control Completer(for LDA, LHA, etc.) */
- if ( *s == ',' && ( *(s+1) == 'm' || *(s+1) == 'M' ) ) {
- m = 1;
- s += 2;
- }
- else
- m = 0;
-
- opcode |= m << 5;
- while ( *s == ' ' || *s == '\t' ) /* skip to next operand */
- s++;
-
- continue;
- case 'D': /* 26 bit immediate at 31 (to support DIAG instr.) */
- /* the action (and interpretation of this operand is
- implementation dependent) */
- #if defined(OBJ_ELF)
- the_insn.field_selector = pa_chk_field_selector(&s);
- #endif
- getExpression(s);
- if ( the_insn.exp.X_seg == &bfd_abs_section ) {
- opcode |= ( (evaluateAbsolute(the_insn.exp,the_insn.field_selector) & 0x1ffffff) << 1 );
- #ifdef NEW_SOM /* XXX what replaces this? */
- /* PJH: VERY unsure about the following */
- the_insn.field_selector = the_insn.exp.field_selector;
- #endif
- }
- else
- as_bad("Illegal DIAG operand");
- s = expr_end;
- continue;
- case 'f': /* 3 bit Special Function Unit (SFU) identifier at 25 */
- sfu = pa_parse_number(&s);
- if ( (sfu > 7) || (sfu < 0) )
- as_bad("Illegal SFU identifier: %02x", sfu);
- opcode |= (sfu & 7) << 6;
- continue;
- case 'O': /* 20 bit SFU op. split between 15 bits at 20
- and 5 bits at 31 */
- getExpression(s);
- s = expr_end;
- continue;
- case 'o': /* 15 bit Special Function Unit operation at 20 */
- getExpression(s);
- s = expr_end;
- continue;
- case '2': /* 22 bit SFU op. split between 17 bits at 20
- and 5 bits at 31 */
- getExpression(s);
- s = expr_end;
- continue;
- case '1': /* 15 bit SFU op. split between 10 bits at 20
- and 5 bits at 31 */
- getExpression(s);
- s = expr_end;
- continue;
- case '0': /* 10 bit SFU op. split between 5 bits at 20
- and 5 bits at 31 */
- getExpression(s);
- s = expr_end;
- continue;
- case 'u': /* 3 bit coprocessor unit identifier at 25 */
- getExpression(s);
- s = expr_end;
- continue;
- case 'F': /* Source FP Operand Format Completer (2 bits at 20) */
- f = pa_parse_fp_format(&s);
- opcode |= (int)f << 11;
- the_insn.fpof1 = f;
- continue;
- case 'G': /* Destination FP Operand Format Completer (2 bits at 18) */
- s--; /* need to pass the previous comma to pa_parse_fp_format */
- f = pa_parse_fp_format(&s);
- opcode |= (int)f << 13;
- the_insn.fpof2 = f;
- continue;
- case 'M': /* FP Compare Conditions (encoded as 5 bits at 31) */
- cond = pa_parse_fp_cmp_cond(&s);
- opcode |= cond;
- continue;
-
- case 'v': /* a 't' type extended to handle L/R register halves. */
- {
- struct pa_89_fp_reg_struct result;
- int status;
-
- pa_89_parse_number(&s,&result);
- if ( result.number_part < 32 && result.number_part >= 0 ) {
- opcode |= (result.number_part & 0x1f);
-
- /* 0x30 opcodes are FP arithmetic operation opcodes */
- /* load/store FP opcodes do not get converted to 0x38 */
- /* opcodes like the 0x30 opcodes do */
- if ( need_89_opcode(&the_insn,&result) ) {
- if ( (opcode & 0xfc000000) == 0x30000000 ) {
- opcode |= (result.L_R_select & 1) << 6;
- opcode |= 1 << 27;
- }
- else {
- opcode |= (result.L_R_select & 1) << 6;
- }
- }
- continue;
- }
- }
- break;
- case 'E': /* a 'b' type extended to handle L/R register halves. */
- {
- struct pa_89_fp_reg_struct result;
- int status;
-
- pa_89_parse_number(&s,&result);
- if ( result.number_part < 32 && result.number_part >= 0 ) {
- opcode |= (result.number_part & 0x1f) << 21;
- if ( need_89_opcode(&the_insn,&result) ) {
- opcode |= (result.L_R_select & 1) << 7;
- opcode |= 1 << 27;
- }
- continue;
- }
- }
- break;
-
- case 'X': /* an 'x' type extended to handle L/R register halves. */
- {
- struct pa_89_fp_reg_struct result;
- int status;
-
-
- pa_89_parse_number(&s,&result);
- if ( result.number_part < 32 && result.number_part >= 0 ) {
- opcode |= (result.number_part & 0x1f) << 16;
- if ( need_89_opcode(&the_insn,&result) ) {
- opcode |= (result.L_R_select & 1) << 12;
- opcode |= 1 << 27;
- }
- continue;
- }
- }
- break;
-
- case '4': /* 5 bit register field at 10
- (used in 'fmpyadd' and 'fmpysub') */
- {
- struct pa_89_fp_reg_struct result;
- int status;
-
- status = pa_89_parse_number(&s,&result);
- if ( result.number_part < 32 && result.number_part >= 0 ) {
- if ( the_insn.fpof1 == SGL ) {
- result.number_part &= 0xF;
- result.number_part |= (result.L_R_select & 1) << 4;
- }
- opcode |= result.number_part << 21;
- continue;
- }
- }
- break;
-
- case '6': /* 5 bit register field at 15
- (used in 'fmpyadd' and 'fmpysub') */
- {
- struct pa_89_fp_reg_struct result;
- int status;
-
- status = pa_89_parse_number(&s,&result);
- if ( result.number_part < 32 && result.number_part >= 0 ) {
- if ( the_insn.fpof1 == SGL ) {
- result.number_part &= 0xF;
- result.number_part |= (result.L_R_select & 1) << 4;
- }
- opcode |= result.number_part << 16;
- continue;
- }
- }
- break;
-
- case '7': /* 5 bit register field at 31
- (used in 'fmpyadd' and 'fmpysub') */
- {
- struct pa_89_fp_reg_struct result;
- int status;
-
- status = pa_89_parse_number(&s,&result);
- if ( result.number_part < 32 && result.number_part >= 0 ) {
- if ( the_insn.fpof1 == SGL ) {
- result.number_part &= 0xF;
- result.number_part |= (result.L_R_select & 1) << 4;
- }
- opcode |= result.number_part;
- continue;
- }
- }
- break;
-
- case '8': /* 5 bit register field at 20
- (used in 'fmpyadd' and 'fmpysub') */
- {
- struct pa_89_fp_reg_struct result;
- int status;
-
- status = pa_89_parse_number(&s,&result);
- if ( result.number_part < 32 && result.number_part >= 0 ) {
- if ( the_insn.fpof1 == SGL ) {
- result.number_part &= 0xF;
- result.number_part |= (result.L_R_select & 1) << 4;
- }
- opcode |= result.number_part << 11;
- continue;
- }
- }
- break;
-
- case '9': /* 5 bit register field at 25
- (used in 'fmpyadd' and 'fmpysub') */
- {
- struct pa_89_fp_reg_struct result;
- int status;
-
- status = pa_89_parse_number(&s,&result);
- if ( result.number_part < 32 && result.number_part >= 0 ) {
- if ( the_insn.fpof1 == SGL ) {
- result.number_part &= 0xF;
- result.number_part |= (result.L_R_select & 1) << 4;
- }
- opcode |= result.number_part << 6;
- continue;
- }
- }
- break;
-
- case 'H': /* Floating Point Operand Format at 26 for */
- /* 'fmpyadd' and 'fmpysub' (very similar to 'F') */
- /* bits are switched from other FP Operand */
- /* formats. 1=SGL, 1=<none>, 0=DBL */
- f = pa_parse_fp_format(&s);
- switch (f) {
- case SGL:
- opcode |= 0x20;
- case DBL:
- the_insn.fpof1 = f;
- continue;
-
- case QUAD:
- case ILLEGAL_FMT:
- default:
- as_bad("Illegal Floating Point Operand Format for this instruction: '%s'",*s);
- }
- break;
-
- default:
- abort();
- }
- break;
- }
- error:
- if (match == FALSE)
- {
- /* Args don't match. */
- if (&insn[1] - pa_opcodes < NUMOPCODES
- && !strcmp(insn->name, insn[1].name))
- {
- ++insn;
- s = argsStart;
- continue;
- }
- else
- {
- as_bad("Illegal operands %s",error_message );
- return;
- }
- }
- break;
- }
-
- the_insn.opcode = opcode;
-
- #ifdef PA_DEBUG
- if ( the_insn.exp.X_add_symbol && the_insn.exp.X_subtract_symbol )
- print_insn_short(&the_insn);
- fprintf(stderr,"*********** END OF STATEMENT\n");
- #endif
-
- return;
- }
-
- /*
- This is identical to the md_atof in m68k.c. I think this is right,
- but I'm not sure.
-
- Turn a string in input_line_pointer into a floating point constant of type
- type, and store the appropriate bytes in *litP. The number of LITTLENUMS
- emitted is stored in *sizeP . An error message is returned, or NULL on OK.
- */
-
- /* Equal to MAX_PRECISION in atof-ieee.c */
- #define MAX_LITTLENUMS 6
-
- char *
- md_atof(type,litP,sizeP)
- char type;
- char *litP;
- int *sizeP;
- {
- int prec;
- LITTLENUM_TYPE words[MAX_LITTLENUMS];
- LITTLENUM_TYPE *wordP;
- char *t;
- char *atof_ieee();
-
- switch(type) {
-
- case 'f':
- case 'F':
- case 's':
- case 'S':
- prec = 2;
- break;
-
- case 'd':
- case 'D':
- case 'r':
- case 'R':
- prec = 4;
- break;
-
- case 'x':
- case 'X':
- prec = 6;
- break;
-
- case 'p':
- case 'P':
- prec = 6;
- break;
-
- default:
- *sizeP=0;
- return "Bad call to MD_ATOF()";
- }
- t=atof_ieee(input_line_pointer,type,words);
- if(t)
- input_line_pointer=t;
- *sizeP=prec * sizeof(LITTLENUM_TYPE);
- for(wordP=words;prec--;) {
- md_number_to_chars(litP,(long)(*wordP++),sizeof(LITTLENUM_TYPE));
- litP+=sizeof(LITTLENUM_TYPE);
- }
- return ""; /* Someone should teach Dean about null pointers */
- }
-
- /*
- * Write out big-endian.
- */
- void
- md_number_to_chars(buf,val,n)
- char *buf;
- long val;
- int n;
- {
-
- switch(n) {
-
- case 4:
- *buf++ = val >> 24;
- *buf++ = val >> 16;
- case 2:
- *buf++ = val >> 8;
- case 1:
- *buf = val;
- break;
-
- default:
- abort();
- }
- return;
- }
-
- void
- md_create_short_jump(ptr, from_addr, to_addr, frag, to_symbol)
- char *ptr;
- long from_addr, to_addr;
- fragS *frag;
- symbolS *to_symbol;
- {
- fprintf(stderr, "pa_create_short_jmp\n");
- abort();
- }
-
- void
- md_number_to_disp(buf,val,n)
- char *buf;
- long val;
- int n;
- {
- fprintf(stderr, "md_number_to_disp\n");
- abort();
- }
-
- void
- md_number_to_field(buf,val,fix)
- char *buf;
- long val;
- void *fix;
- {
- fprintf(stderr, "pa_number_to_field\n");
- abort();
- }
-
- /* the bit-field entries in the relocation_info struct plays hell
- with the byte-order problems of cross-assembly. So as a hack,
- I added this mach. dependent ri twiddler. Ugly, but it gets
- you there. -KWK */
- /* on sparc: first 4 bytes are normal unsigned long address, next three
- bytes are index, most sig. byte first. Byte 7 is broken up with
- bit 7 as external, bits 6 & 5 unused, and the lower
- five bits as relocation type. Next 4 bytes are long int addend. */
- /* Thanx and a tip of the hat to Michael Bloom, mb@ttidca.tti.com */
-
- #ifdef OBJ_SOM
- void
- md_ri_to_chars(ri_p, ri)
- struct reloc_info_pa *ri_p, ri;
- {
- unsigned char the_bytes[sizeof(*ri_p)];
- #if defined(OBJ_SOM) | defined(OBJ_OSFROSE) | defined(OBJ_ELF)
- /* not sure what, if any, changes are required for new-style cross-assembly */
- #else
- the_bytes[0] = ((ri.need_data_ref << 7) & 0x80) | ((ri.arg_reloc & 0x03f8) >> 3);
- the_bytes[1] = ((ri.arg_reloc & 0x07) << 5) | ri.expression_type;
- the_bytes[2] = ((ri.exec_level << 6) & 0xc0) | ri.fixup_format;
- the_bytes[3] = ri.fixup_field & 0xff;
- md_number_to_chars(&the_bytes[4], ri.subspace_offset, sizeof(ri.subspace_offset));
- md_number_to_chars(&the_bytes[8], ri.symbol_index_one, sizeof(ri.symbol_index_one));
- md_number_to_chars(&the_bytes[12], ri.symbol_index_two, sizeof(ri.symbol_index_two));
- md_number_to_chars(&the_bytes[16], ri.fixup_constant, sizeof(ri.fixup_constant));
-
- /* now put it back where you found it, Junior... */
- bcopy (the_bytes, (char *)ri_p, sizeof(*ri_p));
- #endif
-
- }
- #endif
-
-
- /* Translate internal representation of relocation info to BFD target
- format. */
-
- arelent * tc_gen_reloc (section, fixp)
- asection * section;
- fixS * fixp;
- {
- arelent *reloc;
- hppa_fixS *hppa_fixp = hppa_find_hppa_fix(fixp);
- bfd_reloc_code_real_type code;
- static int unwind_reloc_fixp_cnt = 0;
- static arelent *unwind_reloc_entryP = NULL;
-
- if ( fixp->fx_addsy == 0 )
- return 0;
- assert (hppa_fixp != 0);
- assert (section != 0);
-
- /* unwind section relocations are handled in a special way. */
- /* The relocations for the .unwind section are originally */
- /* built in the usual way. That is, for each unwind table */
- /* entry there are two relocations: one for the beginning of */
- /* the function and one for the end. */
-
- /* The first time we enter this function we create a */
- /* relocation of the type R_HPPA_UNWIND_ENTRIES. The addend */
- /* of the relocation is initialized to 0. Each additional */
- /* pair of times this function is called for the unwind */
- /* section represents an additional unwind table entry. Thus, */
- /* the addend of the relocation should end up to be the number */
- /* of unwind table entries. */
- if ( strcmp(UNWIND_SECTION_NAME,section->name) == 0 ) {
- if ( unwind_reloc_entryP == NULL ) {
- reloc = (arelent *) bfd_alloc_by_size_t (stdoutput, sizeof (arelent));
- assert (reloc != 0);
- unwind_reloc_entryP = reloc;
- unwind_reloc_fixp_cnt++;
- unwind_reloc_entryP->address = fixp->fx_frag->fr_address + fixp->fx_where;
- /* a pointer any function will do. We only */
- /* need one to tell us what section the unwind */
- /* relocations are for. */
- unwind_reloc_entryP->sym_ptr_ptr = &fixp->fx_addsy->bsym;
- code = R_HPPA_UNWIND_ENTRIES;
- unwind_reloc_entryP->howto = bfd_reloc_type_lookup (stdoutput, code);
- unwind_reloc_entryP->addend = unwind_reloc_fixp_cnt / 2;
-
- return unwind_reloc_entryP;
- }
- unwind_reloc_fixp_cnt++;
- unwind_reloc_entryP->addend = unwind_reloc_fixp_cnt / 2;
-
- return NULL;
- }
-
- reloc = (arelent *) bfd_alloc_by_size_t (stdoutput, sizeof (arelent));
- assert (reloc != 0);
-
- reloc->sym_ptr_ptr = &fixp->fx_addsy->bsym;
- /* XXX: might need additional processing here */
- /* hppa_elf_gen_reloc_type() is defined in the */
- /* ELF/PA BFD back-end */
- code = hppa_elf_gen_reloc_type(fixp->fx_r_type,
- hppa_fixp->fx_r_format,
- hppa_fixp->fx_r_field);
- reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
-
- assert(code == reloc->howto->type);
-
- reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
- reloc->addend = 0; /* default */
-
- /* Now, do any processing that is dependent on the relocation */
- /* type. */
- switch ( code ) {
- case R_HPPA_PLABEL_32:
- case R_HPPA_PLABEL_11:
- case R_HPPA_PLABEL_14:
- case R_HPPA_PLABEL_L21:
- case R_HPPA_PLABEL_R11:
- case R_HPPA_PLABEL_R14:
- /* For plabel relocations, the addend of the */
- /* relocation should be either 0 (no static link) or 2 */
- /* (static link required). */
- /* XXX: assume that fx_addnumber contains this */
- /* information */
- reloc->addend = fixp->fx_addnumber;
- break;
-
- case R_HPPA_ABS_CALL_11:
- case R_HPPA_ABS_CALL_14:
- case R_HPPA_ABS_CALL_17:
- case R_HPPA_ABS_CALL_L21:
- case R_HPPA_ABS_CALL_R11:
- case R_HPPA_ABS_CALL_R14:
- case R_HPPA_ABS_CALL_R17:
- case R_HPPA_ABS_CALL_LS21:
- case R_HPPA_ABS_CALL_RS11:
- case R_HPPA_ABS_CALL_RS14:
- case R_HPPA_ABS_CALL_RS17:
- case R_HPPA_ABS_CALL_LD21:
- case R_HPPA_ABS_CALL_RD11:
- case R_HPPA_ABS_CALL_RD14:
- case R_HPPA_ABS_CALL_RD17:
- case R_HPPA_ABS_CALL_LR21:
- case R_HPPA_ABS_CALL_RR14:
- case R_HPPA_ABS_CALL_RR17:
-
- case R_HPPA_PCREL_CALL_11:
- case R_HPPA_PCREL_CALL_14:
- case R_HPPA_PCREL_CALL_17:
- case R_HPPA_PCREL_CALL_L21:
- case R_HPPA_PCREL_CALL_R11:
- case R_HPPA_PCREL_CALL_R14:
- case R_HPPA_PCREL_CALL_R17:
- case R_HPPA_PCREL_CALL_LS21:
- case R_HPPA_PCREL_CALL_RS11:
- case R_HPPA_PCREL_CALL_RS14:
- case R_HPPA_PCREL_CALL_RS17:
- case R_HPPA_PCREL_CALL_LD21:
- case R_HPPA_PCREL_CALL_RD11:
- case R_HPPA_PCREL_CALL_RD14:
- case R_HPPA_PCREL_CALL_RD17:
- case R_HPPA_PCREL_CALL_LR21:
- case R_HPPA_PCREL_CALL_RR14:
- case R_HPPA_PCREL_CALL_RR17:
- /* constant is stored in the instruction */
- reloc->addend = ELF32_HPPA_R_ADDEND(hppa_fixp->fx_arg_reloc,0);
- break;
- default:
- reloc->addend = fixp->fx_addnumber;
- break;
- }
-
- return reloc;
- }
-
- void
- md_convert_frag(abfd, sec, fragP)
- register bfd *abfd;
- register asection *sec;
- register fragS *fragP;
- {
- unsigned int address;
-
- if ( fragP -> fr_type == rs_machine_dependent ) {
- switch ( (int) fragP -> fr_subtype ) {
- case 0:
- fragP -> fr_type = rs_fill;
- know( fragP -> fr_var == 1 );
- know( fragP -> fr_next );
- address = fragP -> fr_address + fragP -> fr_fix;
- if ( address % fragP -> fr_offset ) {
- fragP -> fr_offset =
- fragP -> fr_next -> fr_address
- - fragP -> fr_address
- - fragP -> fr_fix;
- }
- else
- fragP -> fr_offset = 0;
- break;
- }
- }
- }
-
- /* Round up a section size to the appropriate boundary. */
- long
- md_section_align (segment, size)
- asection *segment;
- long size;
- {
- return (size + 7) & ~7; /* Round all sects to multiple of 8 */
- } /* md_section_align() */
-
- void
- md_create_long_jump(ptr, from_addr, to_addr, frag, to_symbol)
- char *ptr;
- long from_addr,
- to_addr;
- fragS *frag;
- symbolS *to_symbol;
- {
- fprintf(stderr, "pa_create_long_jump\n");
- abort();
- }
-
- int
- /* md_estimate_size_before_relax(fragP, segtype) */
- md_estimate_size_before_relax(fragP, segment)
- register fragS *fragP;
- asection *segment;
- {
- int size;
-
- size = 0;
-
- while ( (fragP->fr_fix + size) % fragP->fr_offset )
- size++;
-
- return size;
- }
-
- int
- md_parse_option(argP,cntP,vecP)
- char **argP;
- int *cntP;
- char ***vecP;
- {
- return 1;
- }
-
- /* We have no need to default values of symbols. */
-
- /* ARGSUSED */
- symbolS *md_undefined_symbol(name)
- char *name;
- {
- return 0;
- } /*md_undefined_symbol() */
-
- /* Parse an operand that is machine-specific.
- We just return without modifying the expression if we have nothing
- to do. */
-
- /* ARGSUSED */
- void
- md_operand (expressionP)
- expressionS *expressionP;
- {
- }
-
- /* Apply a fixS to the frags, now that we know the value it ought to
- hold. */
-
- int apply_field_selector(value,constant,field_selector)
- long value;
- long constant;
- int field_selector;
- {
- /* hppa_field_adjust() is defined in the HPPA target */
- return hppa_field_adjust(value,constant,field_selector);
- }
-
- void md_apply_fix(fixP, val)
- fixS *fixP;
- long val;
- {
- char *buf = fixP->fx_where + fixP->fx_frag->fr_literal;
- hppa_fixS *hppa_fixP = hppa_find_hppa_fix(fixP);
- long new_val;
- long result;
- unsigned int w1,w2,w;
- /* The following routine is defined in the ELF/PA back-end */
- extern unsigned char hppa_elf_insn2fmt();
-
- if ( hppa_fixP ) {
- unsigned char fmt = hppa_elf_insn2fmt(fixP->fx_r_type,
- *(unsigned long *)buf);
-
- assert(fixP->fx_r_type < R_HPPA_UNIMPLEMENTED);
- assert(fixP->fx_r_type >= R_HPPA_NONE);
-
- fixP->fx_addnumber = val; /* Remember value for emit_reloc */
-
- /* Check if this is an undefined symbol. No relocation can */
- /* possibly be performed in this case. */
-
- if ( (fixP->fx_addsy && fixP->fx_addsy->bsym->section == &bfd_und_section)
- || (fixP->fx_subsy && fixP->fx_subsy->bsym->section == &bfd_und_section) )
- return;
-
- /* Perform some processing particular to unwind */
- /* relocations */
-
- if ( hppa_fixP->fx_call_infop
- && ( ( (fixP == hppa_fixP->fx_call_infop->start_fix)
- && (fixP->fx_addsy ==
- hppa_fixP->fx_call_infop->start_symbol) )
- || ( (fixP == hppa_fixP->fx_call_infop->end_fix)
- && (fixP->fx_addsy ==
- hppa_fixP->fx_call_infop->end_symbol) )
- ) )
- val += fixP->fx_addsy->sy_frag->fr_address;
-
- switch (fmt) {
-
- case 14: /* all the opcodes with the 'j' operand type */
- new_val = apply_field_selector(val,0,hppa_fixP->fx_r_field);
- /* need to check for overflow here */
-
- /* mask off 14 bits to be changed */
- *(long *)buf = *(long *)buf & 0xffffc000;
- low_sign_unext(new_val,14,&result);
- break;
-
- case 21: /* all the opcodes with the 'k' operand type */
- new_val = apply_field_selector(val,0,hppa_fixP->fx_r_field);
- /* need to check for overflow here */
-
- /* mask off 21 bits to be changed */
- *(long *)buf = *(long *)buf & 0xffe00000;
- dis_assemble_21(new_val,&result);
- break;
-
- case 11: /* all the opcodes with the 'i' operand type */
- new_val = apply_field_selector(val,0,hppa_fixP->fx_r_field);
- /* need to check for overflow here */
-
- /* mask off 11 bits to be changed */
- *(long *)buf = *(long *)buf & 0xffff800;
- low_sign_unext(new_val,11,&result);
- break;
-
- case 12: /* all the opcodes with the 'w' operand type */
- new_val = apply_field_selector(val,0,hppa_fixP->fx_r_field);
-
- /* mask off 11 bits to be changed */
- sign_unext( (new_val - 8) >> 2,12,&result);
- *(long *)buf = *(long *)buf & 0xffffe002;
-
- dis_assemble_12(result,&w1,&w);
- result = ( ( w1 << 2 ) | w );
- break;
-
- case 17: /* some of the opcodes with the 'W' operand type */
- new_val = apply_field_selector(val,0,hppa_fixP->fx_r_field);
- /* need to check for overflow here */
-
- /* mask off 17 bits to be changed */
- *(long *)buf = *(long *)buf & 0xffe0e002;
- sign_unext( (new_val - 8) >> 2,17,&result);
- dis_assemble_17(result,&w1,&w2,&w);
- result = ( ( w2 << 2 ) | ( w1 << 16 ) | w );
- break;
-
- case 32:
- new_val = apply_field_selector(val,0,hppa_fixP->fx_r_field);
- result = new_val; /* no transformation on result */
- *(long *)buf = 0; /* clear out everything */
- break;
-
- case 0:
- return;
-
- default:
- as_bad("bad relocation type/fmt: 0x%02x/0x%02x",
- fixP->fx_r_type, fmt);
- return;
- }
- buf[0] |= (result & 0xff000000) >> 24;
- buf[1] |= (result & 0x00ff0000) >> 16;
- buf[2] |= (result & 0x0000ff00) >> 8;
- buf[3] |= result & 0x000000ff;
- /* We've now adjusted for fx_addnumber, we can */
- /* forget it now. */
- fixP->fx_addnumber = 0;
- }
- else {
- printf("no hppa_fixup entry for this fixup (fixP = 0x%x, type = 0x%x)\n",
- fixP, fixP->fx_r_type);
- }
- } /* md_apply_fix() */
-
- /* Exactly what point is a PC-relative offset relative TO?
- On the PA, they're relative to the address of the offset.
- (??? Is this right? FIXME-SOON) */
- long md_pcrel_from(fixP)
- fixS *fixP;
- {
- return fixP->fx_where + fixP->fx_frag->fr_address;
- } /* md_pcrel_from() */
-
- int is_end_of_statement()
- {
- return ( (*input_line_pointer == '\n')
- || (*input_line_pointer == ';')
- || (*input_line_pointer == '!') );
- }
-
- /* pa-aux.c -- Assembler for the PA - PA-RISC specific support routines */
-
- struct aux_hdr_list *aux_hdr_root = NULL;
-
- int print_errors = 1;
-
- void pa_skip(s)
- char **s;
- {
- while ( **s == ' ' || **s == '\t' )
- *s = *s + 1;
- }
-
- int pa_parse_number(s)
- char **s;
- {
- int num;
- char *name;
- char c;
- symbolS *sym;
- int status;
- char * p = *s;
-
- while ( *p == ' ' || *p == '\t' )
- p = p + 1;
- num=-1; /* assume invalid number to begin with */
- if (isdigit(*p)) {
- num = 0; /* now we know it is a number */
-
- if ( *p == '0' && ( *(p+1) == 'x' || *(p+1) == 'X' ) ) { /* hex input */
- p = p + 2;
- while ( isdigit(*p) || ( (*p >= 'a') && (*p <= 'f') )
- || ( (*p >= 'A') && (*p <= 'F') ) ){
- if ( isdigit(*p) )
- num = num*16 + *p-'0';
- else if ( *p >= 'a' && *p <= 'f' )
- num = num*16 + *p-'a' + 10;
- else
- num = num*16 + *p-'A' + 10;
- ++p;
- }
- }
- else {
- while (isdigit(*p)) {
- num= num*10 + *p-'0';
- ++p;
- }
- }
- }
- else if ( *p == '%' ) { /* could be a pre-defined register */
- num = 0;
- name = p;
- p++;
- c = *p;
- /* tege hack: Special case for general registers
- as the general code makes a binary search with case translation,
- and is VERY slow. */
- if (c == 'r') {
- p++;
- if ( *p == 'e' && *(p+1) == 't' && (*(p+2) == '0' || *(p+2) == '1') ) {
- p += 2;
- num = *p - '0' + 28; /* r28 is ret0 */
- p++;
- }
- else if (!isdigit(*p))
- as_bad("Undefined register: '%s'. ASSUMING 0",name);
- else {
- do
- num= num*10 + *p++ - '0';
- while (isdigit(*p));
- }
- }
- else {
- while ( is_part_of_name(c) ) {
- p = p + 1;
- c = *p;
- }
- *p = 0;
- status = reg_name_search(name);
- if ( status >= 0 )
- num = status;
- else {
- if ( print_errors )
- as_bad("Undefined register: '%s'. ASSUMING 0",name);
- else
- num = -1;
- }
- *p = c;
- }
- }
- else {
- num = 0;
- name = p;
- c = *p;
- while ( is_part_of_name(c) ) {
- p = p + 1;
- c = *p;
- }
- *p = 0;
- if ( (sym = symbol_find(name)) != NULL ) {
- #ifdef OBJ_SOM
- if ( sym->pa_sy_type == ST_ABSOLUTE ) {
- num = sym->pa_sy_value;
- #else
- if ( S_GET_SEGMENT(sym) == &bfd_abs_section ) {
- num = S_GET_VALUE(sym);
- #endif
- }
- else {
- if ( print_errors )
- as_bad("Non-absolute constant: '%s'. ASSUMING 0",name);
- else
- num = -1;
- }
- }
- else {
- if ( print_errors )
- as_bad("Undefined absolute constant: '%s'. ASSUMING 0",name);
- else
- num = -1;
- }
- *p = c;
- }
-
- *s = p;
- return num;
- }
-
- struct pd_reg {
- char *name;
- int value;
- };
-
- /* List of registers that are pre-defined:
-
- General Registers:
-
- Name Value Name Value
- %r0 0 %r16 16
- %r1 1 %r17 17
- %r2 2 %r18 18
- %r3 3 %r19 19
- %r4 4 %r20 20
- %r5 5 %r21 21
- %r6 6 %r22 22
- %r7 7 %r23 23
- %r8 8 %r24 24
- %r9 9 %r25 25
- %r10 10 %r26 26
- %r11 11 %r27 27
- %r12 12 %r28 28
- %r13 13 %r29 29
- %r14 14 %r30 30
- %r15 15 %r31 31
-
- Floating-point Registers:
- [NOTE: Also includes L and R versions of these (e.g. %fr19L, %fr19R)]
-
- Name Value Name Value
- %fr0 0 %fr16 16
- %fr1 1 %fr17 17
- %fr2 2 %fr18 18
- %fr3 3 %fr19 19
- %fr4 4 %fr20 20
- %fr5 5 %fr21 21
- %fr6 6 %fr22 22
- %fr7 7 %fr23 23
- %fr8 8 %fr24 24
- %fr9 9 %fr25 25
- %fr10 10 %fr26 26
- %fr11 11 %fr27 27
- %fr12 12 %fr28 28
- %fr13 13 %fr29 29
- %fr14 14 %fr30 30
- %fr15 15 %fr31 31
-
- Space Registers:
-
- Name Value Name Value
- %sr0 0 %sr4 4
- %sr1 1 %sr5 5
- %sr2 2 %sr6 6
- %sr3 3 %sr7 7
-
- Control registers and their synonyms:
-
- Names Value
- %cr0 %rctr 0
- %cr8 %pidr1 8
- %cr9 %pidr2 9
- %cr10 %ccr 10
- %cr11 %sar 11
- %cr12 %pidr3 12
- %cr13 %pidr4 13
- %cr14 %iva 14
- %cr15 %eiem 15
- %cr16 %itmr 16
- %cr17 %pcsq 17
- %cr18 %pcoq 18
- %cr19 %iir 19
- %cr20 %isr 20
- %cr21 %ior 21
- %cr22 %ipsw 22
- %cr23 %eirr 23
- %cr24 %tr0 %ppda 24
- %cr25 %tr1 %hta 25
- %cr26 %tr2 26
- %cr27 %tr3 27
- %cr28 %tr4 28
- %cr29 %tr5 29
- %cr30 %tr6 30
- %cr31 %tr7 31
-
- Miscellaneous registers and their synonyms:
-
- Names Value
- %arg0 26
- %arg1 25
- %arg2 24
- %arg3 23
- %sp 30
- %ret0 28
- %ret1 29
- */
-
- /* This table is sorted. Suitable for searching by a binary search. */
-
- static struct pd_reg pre_defined_registers[] = {
- { "%arg0", 26 },
- { "%arg1", 25 },
- { "%arg2", 24 },
- { "%arg3", 23 },
- { "%cr0", 0 },
- { "%cr10", 10 },
- { "%cr11", 11 },
- { "%cr12", 12 },
- { "%cr13", 13 },
- { "%cr14", 14 },
- { "%cr15", 15 },
- { "%cr16", 16 },
- { "%cr17", 17 },
- { "%cr18", 18 },
- { "%cr19", 19 },
- { "%cr20", 20 },
- { "%cr21", 21 },
- { "%cr22", 22 },
- { "%cr23", 23 },
- { "%cr24", 24 },
- { "%cr25", 25 },
- { "%cr26", 26 },
- { "%cr27", 27 },
- { "%cr28", 28 },
- { "%cr29", 29 },
- { "%cr30", 30 },
- { "%cr31", 31 },
- { "%cr8", 8 },
- { "%cr9", 9 },
- { "%eiem", 15 },
- { "%eirr", 23 },
- { "%fr0", 0 },
- { "%fr0L", 0 },
- { "%fr0R", 0 },
- { "%fr1", 1 },
- { "%fr10", 10 },
- { "%fr10L", 10 },
- { "%fr10R", 10 },
- { "%fr11", 11 },
- { "%fr11L", 11 },
- { "%fr11R", 11 },
- { "%fr12", 12 },
- { "%fr12L", 12 },
- { "%fr12R", 12 },
- { "%fr13", 13 },
- { "%fr13L", 13 },
- { "%fr13R", 13 },
- { "%fr14", 14 },
- { "%fr14L", 14 },
- { "%fr14R", 14 },
- { "%fr15", 15 },
- { "%fr15L", 15 },
- { "%fr15R", 15 },
- { "%fr16", 16 },
- { "%fr16L", 16 },
- { "%fr16R", 16 },
- { "%fr17", 17 },
- { "%fr17L", 17 },
- { "%fr17R", 17 },
- { "%fr18", 18 },
- { "%fr18L", 18 },
- { "%fr18R", 18 },
- { "%fr19", 19 },
- { "%fr19L", 19 },
- { "%fr19R", 19 },
- { "%fr1L", 1 },
- { "%fr1R", 1 },
- { "%fr2", 2 },
- { "%fr20", 20 },
- { "%fr20L", 20 },
- { "%fr20R", 20 },
- { "%fr21", 21 },
- { "%fr21L", 21 },
- { "%fr21R", 21 },
- { "%fr22", 22 },
- { "%fr22L", 22 },
- { "%fr22R", 22 },
- { "%fr23", 23 },
- { "%fr23L", 23 },
- { "%fr23R", 23 },
- { "%fr24", 24 },
- { "%fr24L", 24 },
- { "%fr24R", 24 },
- { "%fr25", 25 },
- { "%fr25L", 25 },
- { "%fr25R", 25 },
- { "%fr26", 26 },
- { "%fr26L", 26 },
- { "%fr26R", 26 },
- { "%fr27", 27 },
- { "%fr27L", 27 },
- { "%fr27R", 27 },
- { "%fr28", 28 },
- { "%fr28L", 28 },
- { "%fr28R", 28 },
- { "%fr29", 29 },
- { "%fr29L", 29 },
- { "%fr29R", 29 },
- { "%fr2L", 2 },
- { "%fr2R", 2 },
- { "%fr3", 3 },
- { "%fr30", 30 },
- { "%fr30L", 30 },
- { "%fr30R", 30 },
- { "%fr31", 31 },
- { "%fr31L", 31 },
- { "%fr31R", 31 },
- { "%fr3L", 3 },
- { "%fr3R", 3 },
- { "%fr4", 4 },
- { "%fr4L", 4 },
- { "%fr4R", 4 },
- { "%fr5", 5 },
- { "%fr5L", 5 },
- { "%fr5R", 5 },
- { "%fr6", 6 },
- { "%fr6L", 6 },
- { "%fr6R", 6 },
- { "%fr7", 7 },
- { "%fr7L", 7 },
- { "%fr7R", 7 },
- { "%fr8", 8 },
- { "%fr8L", 8 },
- { "%fr8R", 8 },
- { "%fr9", 9 },
- { "%fr9L", 9 },
- { "%fr9R", 9 },
- { "%hta", 25 },
- { "%iir", 19 },
- { "%ior", 21 },
- { "%ipsw", 22 },
- { "%isr", 20 },
- { "%itmr", 16 },
- { "%iva", 14 },
- { "%pcoq", 18 },
- { "%pcsq", 17 },
- { "%pidr1", 8 },
- { "%pidr2", 9 },
- { "%pidr3", 12 },
- { "%pidr4", 13 },
- { "%ppda", 24 },
- { "%r0", 0 },
- { "%r1", 1 },
- { "%r10", 10 },
- { "%r11", 11 },
- { "%r12", 12 },
- { "%r13", 13 },
- { "%r14", 14 },
- { "%r15", 15 },
- { "%r16", 16 },
- { "%r17", 17 },
- { "%r18", 18 },
- { "%r19", 19 },
- { "%r2", 2 },
- { "%r20", 20 },
- { "%r21", 21 },
- { "%r22", 22 },
- { "%r23", 23 },
- { "%r24", 24 },
- { "%r25", 25 },
- { "%r26", 26 },
- { "%r27", 27 },
- { "%r28", 28 },
- { "%r29", 29 },
- { "%r3", 3 },
- { "%r30", 30 },
- { "%r31", 31 },
- { "%r4", 4 },
- { "%r4L", 4 },
- { "%r4R", 4 },
- { "%r5", 5 },
- { "%r5L", 5 },
- { "%r5R", 5 },
- { "%r6", 6 },
- { "%r6L", 6 },
- { "%r6R", 6 },
- { "%r7", 7 },
- { "%r7L", 7 },
- { "%r7R", 7 },
- { "%r8", 8 },
- { "%r8L", 8 },
- { "%r8R", 8 },
- { "%r9", 9 },
- { "%r9L", 9 },
- { "%r9R", 9 },
- { "%rctr",0 },
- { "%ret0",28 },
- { "%ret1",29 },
- { "%sar", 11 },
- { "%sp", 30 },
- { "%sr0", 0 },
- { "%sr1", 1 },
- { "%sr2", 2 },
- { "%sr3", 3 },
- { "%sr4", 4 },
- { "%sr5", 5 },
- { "%sr6", 6 },
- { "%sr7", 7 },
- { "%tr0", 24 },
- { "%tr1", 25 },
- { "%tr2", 26 },
- { "%tr3", 27 },
- { "%tr4", 28 },
- { "%tr5", 29 },
- { "%tr6", 30 },
- { "%tr7", 31 }
- };
-
- #define REG_NAME_CNT (sizeof(pre_defined_registers) / sizeof(struct pd_reg))
-
- int reg_name_search(name)
- char *name;
- {
- int x,l,r;
-
- l = 0;
- r = REG_NAME_CNT - 1;
-
- do {
- x = (l + r) / 2;
- if (strcasecmp(name,pre_defined_registers[x].name) < 0)
- r = x - 1;
- else
- l = x + 1;
- } while ( !( (strcasecmp(name,pre_defined_registers[x].name) == 0) ||
- (l > r) ) );
-
- if ( strcasecmp(name,pre_defined_registers[x].name) == 0 )
- return(pre_defined_registers[x].value);
- else
- return(-1);
-
- }
-
- int is_pre_defined_register(s)
- char *s;
- {
- if ( reg_name_search(s) >= 0 )
- return(TRUE);
- else
- return(FALSE);
- }
-
- int is_R_select(s)
- char *s;
- {
-
- if ( *s == 'R' || *s == 'r' )
- return(TRUE);
- else
- return(FALSE);
- }
-
- int is_L_select(s)
- char *s;
- {
-
- if ( *s == 'L' || *s == 'l' )
- return(TRUE);
- else
- return(FALSE);
- }
-
- int need_89_opcode(insn,result)
- struct pa_it *insn;
- struct pa_89_fp_reg_struct *result;
- {
- /* if ( result->L_R_select == 1 || insn->fpof1 == DBL || insn->fpof2 == DBL ) */
- /* if (result->L_R_select == 1 && !(insn->fpof1 == DBL || insn->fpof2 == DBL) ) */
- if ( result->L_R_select == 1 && !(insn->fpof1 == DBL && insn->fpof2 == DBL) )
- /* if ( insn->fpof1 == DBL || insn->fpof2 == DBL ) */
- return TRUE;
- else
- return FALSE;
- }
-
- int
- pa_89_parse_number(s,result)
- char **s;
- struct pa_89_fp_reg_struct *result;
- {
- int num;
- char *name;
- char c;
- symbolS *sym;
- int status;
- char * p = *s;
-
- while ( *p == ' ' || *p == '\t' )
- p = p + 1;
- num=-1; /* assume invalid number to begin with */
- result->number_part = -1;
- result->L_R_select = -1;
-
- if (isdigit(*p)) {
- num = 0; /* now we know it is a number */
-
- if ( *p == '0' && ( *(p+1) == 'x' || *(p+1) == 'X' ) ) { /* hex input */
- p = p + 2;
- while ( isdigit(*p) || ( (*p >= 'a') && (*p <= 'f') )
- || ( (*p >= 'A') && (*p <= 'F') ) ){
- if ( isdigit(*p) )
- num = num*16 + *p-'0';
- else if ( *p >= 'a' && *p <= 'f' )
- num = num*16 + *p-'a' + 10;
- else
- num = num*16 + *p-'A' + 10;
- ++p;
- }
- }
- else {
- while (isdigit(*p)) {
- num= num*10 + *p-'0';
- ++p;
- }
- }
-
- result->number_part = num;
-
- if ( is_R_select(p) ) {
- result->L_R_select = 1;
- ++p;
- }
- else if ( is_L_select(p) ) {
- result->L_R_select = 0;
- ++p;
- }
- else
- result->L_R_select = 0;
-
- }
- else if ( *p == '%' ) { /* could be a pre-defined register */
- num = 0;
- name = p;
- p++;
- c = *p;
- /* tege hack: Special case for general registers
- as the general code makes a binary search with case translation,
- and is VERY slow. */
- if (c == 'r') {
- p++;
- if ( *p == 'e' && *(p+1) == 't' && (*(p+2) == '0' || *(p+2) == '1') ) {
- p += 2;
- num = *p - '0' + 28; /* r28 is ret0 */
- p++;
- }
- else if (!isdigit(*p))
- as_bad("Undefined register: '%s'. ASSUMING 0",name);
- else {
- do
- num= num*10 + *p++ - '0';
- while (isdigit(*p));
- }
- }
- else {
- while ( is_part_of_name(c) ) {
- p = p + 1;
- c = *p;
- }
- *p = 0;
- status = reg_name_search(name);
- if ( status >= 0 )
- num = status;
- else {
- if ( print_errors )
- as_bad("Undefined register: '%s'. ASSUMING 0",name);
- else
- num = -1;
- }
- *p = c;
- }
-
- result->number_part = num;
-
- if ( is_R_select(p-1) )
- result->L_R_select = 1;
- else if ( is_L_select(p-1) )
- result->L_R_select = 0;
- else
- result->L_R_select = 0;
-
- }
- else {
- num = 0;
- name = p;
- c = *p;
- while ( is_part_of_name(c) ) {
- p = p + 1;
- c = *p;
- }
- *p = 0;
- if ( (sym = symbol_find(name)) != NULL ) {
- #ifdef OBJ_SOM
- if ( sym->pa_sy_type == ST_ABSOLUTE ) {
- num = sym->pa_sy_value;
- #else
- if ( S_GET_SEGMENT(sym) == &bfd_abs_section ) {
- num = S_GET_VALUE(sym);
- #endif
- }
- else {
- if ( print_errors )
- as_bad("Non-absolute constant: '%s'. ASSUMING 0",name);
- else
- num = -1;
- }
- }
- else {
- if ( print_errors )
- as_bad("Undefined absolute constant: '%s'. ASSUMING 0",name);
- else
- num = -1;
- }
- *p = c;
- result->number_part = num;
-
- if ( is_R_select(p-1) )
- result->L_R_select = 1;
- else if ( is_L_select(p-1) )
- result->L_R_select = 0;
- else
- result->L_R_select = 0;
-
- }
-
- *s = p;
- return num;
-
- }
-
- int pa_parse_fp_cmp_cond(s)
- char **s;
- {
- int cond,i;
- struct possibleS {
- char *string;
- int cond;
- };
-
- /*
- This table is sorted by order of the length of the string. This is so we
- check for <> before we check for <. If we had a <> and checked for < first,
- we would get a false match.
- */
- static struct possibleS poss[] =
- {
- { "false?", 0 },
- { "false", 1 },
- { "true?", 30 },
- { "true", 31 },
- { "!<=>", 3 },
- { "!?>=", 8 },
- { "!?<=", 16 },
- { "!<>", 7 },
- { "!>=", 11 },
- { "!?>", 12 },
- { "?<=", 14 },
- { "!<=", 19 },
- { "!?<", 20 },
- { "?>=", 22 },
- { "!?=", 24 },
- { "!=t", 27 },
- { "<=>", 29 },
- { "=t", 5 },
- { "?=", 6 },
- { "?<", 10 },
- { "<=", 13 },
- { "!>", 15 },
- { "?>", 18 },
- { ">=", 21 },
- { "!<", 23 },
- { "<>", 25 },
- { "!=", 26 },
- { "!?", 28 },
- { "?", 2 },
- { "=", 4 },
- { "<", 9 },
- { ">", 17 }
- };
-
- cond=0;
-
- for ( i = 0; i < 32; i++ ) {
- if ( strncasecmp(*s,poss[i].string,strlen(poss[i].string)) == 0 ) {
- cond = poss[i].cond;
- *s += strlen(poss[i].string);
- while ( **s == ' ' || **s == '\t' )
- *s = *s + 1;
- return cond;
- }
- }
-
- as_bad("Illegal FP Compare Condition: %c",**s);
- return 0;
- }
-
- FP_Operand_Format pa_parse_fp_format(s)
- char **s;
- {
- int f;
-
- f = SGL;
- if ( **s == ',' ) {
- *s += 1;
- if ( strncasecmp(*s,"sgl",3) == 0 ) {
- f = SGL;
- *s += 4;
- }
- else if ( strncasecmp(*s,"dbl",3) == 0 ) {
- f = DBL;
- *s += 4;
- }
- else if ( strncasecmp(*s,"quad",4) == 0 ) {
- f = QUAD;
- *s += 5;
- }
- else {
- f = ILLEGAL_FMT;
- as_bad("Unrecognized FP Operand Format: %3s",*s);
- }
- }
- while ( **s == ' ' || **s == '\t' || **s == 0 )
- *s = *s + 1;
-
- return f;
- }
-
- #if defined(OBJ_ELF)
- int pa_chk_field_selector(str)
- char **str;
- {
- int selector;
- struct selector_entry {
- char *prefix;
- int field_selector;
- };
- static struct selector_entry selector_table[] = {
- { "F'", e_fsel },
- { "F%", e_fsel },
- { "LS'", e_lssel },
- { "LS%", e_lssel },
- { "RS'", e_rssel },
- { "RS%", e_rssel },
- { "L'", e_lsel },
- { "L%", e_lsel },
- { "R'", e_rsel },
- { "R%", e_rsel },
- { "LD'", e_ldsel },
- { "LD%", e_ldsel },
- { "RD'", e_rdsel },
- { "RD%", e_rdsel },
- { "LR'", e_lrsel },
- { "LR%", e_lrsel },
- { "RR'", e_rrsel },
- { "RR%", e_rrsel },
- { "P'", e_psel },
- { "P%", e_psel },
- { "RP'", e_rpsel },
- { "RP%", e_rpsel },
- { "LP'", e_lpsel },
- { "LP%", e_lpsel },
- { "T'", e_tsel },
- { "T%", e_tsel },
- { "RT'", e_rtsel },
- { "RT%", e_rtsel },
- { "LT'", e_ltsel },
- { "LT%", e_ltsel },
- { NULL, e_fsel }
- };
- struct selector_entry *tableP;
-
- selector = e_fsel;
-
- while ( **str == ' ' || **str == '\t' || **str == '\n' || **str == '\f' )
- {
- *str = *str + 1;
- }
- for ( tableP = selector_table; tableP->prefix; tableP++ )
- {
- if ( strncasecmp(tableP->prefix,*str,strlen(tableP->prefix)) == 0 )
- {
- *str += strlen(tableP->prefix);
- selector = tableP->field_selector;
- break;
- }
- }
- return selector;
- }
-
- int
- getExpression(str)
- char *str;
- {
- char *save_in;
- asection * seg;
-
- save_in = input_line_pointer;
- input_line_pointer = str;
- seg = expression(&the_insn.exp);
-
- if (! (seg == &bfd_abs_section
- || seg == &bfd_und_section
- || seg == text_section
- || seg == data_section
- || seg == bss_section
- || seg == diff_section
- || seg == big_section
- || seg == absent_section))
- {
- the_insn.error = "bad segment";
- expr_end = input_line_pointer;
- input_line_pointer=save_in;
- return 1;
- }
- expr_end = input_line_pointer;
- input_line_pointer = save_in;
- return 0;
- }
-
- int
- getAbsoluteExpression(str)
- char *str;
- {
- char *save_in;
- asection * seg;
-
- save_in = input_line_pointer;
- input_line_pointer = str;
- seg = expression(&the_insn.exp);
-
- if ( seg != &bfd_abs_section ) {
- the_insn.error = "segment should be ABSOLUTE";
- expr_end = input_line_pointer;
- input_line_pointer=save_in;
- return 1;
- }
- expr_end = input_line_pointer;
- input_line_pointer = save_in;
- return 0;
- }
-
- #else
- int
- getExpression(str)
- char *str;
- {
- char *save_in;
- segT seg;
-
- save_in = input_line_pointer;
- input_line_pointer = str;
- switch (seg = expression(&the_insn.exp)) {
-
- case SEG_ABSOLUTE:
- case SEG_TEXT:
- case SEG_DATA:
- case SEG_BSS:
- case SEG_UNKNOWN:
- case SEG_DIFFERENCE:
- case SEG_BIG:
- case SEG_GDB:
- case SEG_MILLICODE:
- case SEG_NONE:
- break;
-
- default:
- the_insn.error = "illegal segment";
- expr_end = input_line_pointer;
- input_line_pointer=save_in;
- return 1;
- }
- expr_end = input_line_pointer;
- input_line_pointer = save_in;
- return 0;
- }
-
- int
- getAbsoluteExpression(str)
- char *str;
- {
- char *save_in;
- segT seg;
-
- save_in = input_line_pointer;
- input_line_pointer = str;
- switch (seg = expression(&the_insn.exp)) {
-
- case SEG_ABSOLUTE:
- break;
-
- default:
- the_insn.error = "segment should be ABSOLUTE";
- expr_end = input_line_pointer;
- input_line_pointer=save_in;
- return 1;
- }
- expr_end = input_line_pointer;
- input_line_pointer = save_in;
- return 0;
- }
-
- #endif
-
- int evaluateAbsolute(exp,field_selector)
- expressionS exp;
- int field_selector;
- {
- int value;
-
- value = exp.X_add_number;
-
- if ( exp.X_add_symbol ) {
- value += S_GET_VALUE(exp.X_add_symbol);
- }
- if ( exp.X_subtract_symbol ) {
- value -= S_GET_VALUE(exp.X_subtract_symbol);
- }
-
- switch (field_selector) {
- case e_fsel: /* F : no change */
- break;
-
- case e_lssel: /* LS : if (bit 21) then add 0x800
- arithmetic shift right 11 bits */
- if ( value & 0x00000400 )
- value += 0x800;
- value = (value & 0xfffff800) >> 11;
- break;
-
- case e_rssel: /* RS : Sign extend from bit 21 */
- if ( value & 0x00000400 )
- value |= 0xfffff800;
- else
- value &= 0x7ff;
- break;
-
- case e_lsel: /* L : Arithmetic shift right 11 bits */
- value = (value & 0xfffff800) >> 11;
- break;
-
- case e_rsel: /* R : Set bits 0-20 to zero */
- value = value & 0x7ff;
- break;
-
- case e_ldsel: /* LD : Add 0x800, arithmetic shift
- right 11 bits */
- value += 0x800;
- value = (value & 0xfffff800) >> 11;
- break;
-
- case e_rdsel: /* RD : Set bits 0-20 to one */
- value |= 0xfffff800;
- break;
-
- case e_lrsel: /* LR : L with "rounded" constant */
- /* XXX: this isn't right. Need to add a "rounded" constant */
- /* XXX: (presumably from X_add_number) */
- value = (value & 0xfffff800) >> 11;
- break;
-
- case e_rrsel: /* RR : R with "rounded" constant */
- /* XXX: this isn't right. Need to add a "rounded" constant */
- /* XXX: (presumably from X_add_number) */
- value = value & 0x7ff;
- break;
-
- default:
- BAD_CASE(field_selector);
- break;
- }
- return value;
- }
-
- int pa_build_arg_reloc(type_name)
- char *type_name;
- {
-
- if ( strncasecmp(type_name,"no",2) == 0 ) {
- return 0;
- }
- if ( strncasecmp(type_name,"gr",2) == 0 ) {
- return 1;
- }
- else if ( strncasecmp(type_name,"fr",2) == 0 ) {
- return 2;
- }
- else if ( strncasecmp(type_name,"fu",2) == 0 ) {
- return 3;
- }
- else
- as_bad("Unrecognized argument location: %s\n",type_name);
-
- return 0;
- }
-
- unsigned int pa_align_arg_reloc(reg,arg_reloc)
- unsigned int reg;
- unsigned int arg_reloc;
- {
- unsigned int new_reloc;
-
- new_reloc = arg_reloc;
- switch(reg) {
- case 0:
- new_reloc <<= 8;
- break;
- case 1:
- new_reloc <<= 6;
- break;
- case 2:
- new_reloc <<= 4;
- break;
- case 3:
- new_reloc <<= 2;
- break;
- default:
- as_bad("Illegal argument description: %d",reg);
- }
-
- return new_reloc;
- }
-
- int pa_parse_nullif(s)
- char **s;
- {
- int nullif;
-
- nullif = 0;
- if ( **s == ',' ) {
- *s = *s + 1;
- if ( strncasecmp(*s,"n",1) == 0 )
- nullif = 1;
- else {
- as_bad("Unrecognized Nullification: (%c)",**s);
- nullif = 0;
- }
- *s = *s + 1;
- }
- while ( **s == ' ' || **s == '\t' )
- *s = *s + 1;
-
- return nullif;
- }
-
- #if 0
- int pa_parse_nonneg_cmpsub_cmpltr(s)
- char **s;
- {
- int cmpltr;
- char *name;
- char c;
-
- cmpltr = -1;
- /** cmpltr = 0; **/
- if ( **s == ',' ) {
- *s+=1;
- name = *s;
- while ( **s != ',' && **s != ' ' && **s != '\t' )
- *s += 1;
- c = **s;
- **s = 0x00;
- if ( strcmp(name,"=") == 0 ) {
- cmpltr = 1;
- }
- else if ( strcmp(name,"<") == 0 ) {
- cmpltr = 2;
- }
- else if ( strcmp(name,"<=") == 0 ) {
- cmpltr = 3;
- }
- else if ( strcmp(name,"<<") == 0 ) {
- cmpltr = 4;
- }
- else if ( strcmp(name,"<<=") == 0 ) {
- cmpltr = 5;
- }
- else if ( strcasecmp(name,"sv") == 0 ) {
- cmpltr = 6;
- }
- else if ( strcasecmp(name,"od") == 0 ) {
- cmpltr = 7;
- }
- /**
- else
- cmpltr = -1;
- **/
- **s = c;
- }
- if ( cmpltr >= 0 ) {
- while ( **s == ' ' || **s == '\t' )
- *s = *s + 1;
- }
-
- return cmpltr;
- }
- #endif
- int pa_parse_nonneg_cmpsub_cmpltr(s)
- char **s;
- {
- int cmpltr;
- char *name;
- char c;
-
- cmpltr = 0;
- if ( **s == ',' ) {
- *s+=1;
- name = *s;
- while ( **s != ',' && **s != ' ' && **s != '\t' )
- *s += 1;
- c = **s;
- **s = 0x00;
- if ( strcmp(name,"=") == 0 ) {
- cmpltr = 1;
- }
- else if ( strcmp(name,"<") == 0 ) {
- cmpltr = 2;
- }
- else if ( strcmp(name,"<=") == 0 ) {
- cmpltr = 3;
- }
- else if ( strcmp(name,"<<") == 0 ) {
- cmpltr = 4;
- }
- else if ( strcmp(name,"<<=") == 0 ) {
- cmpltr = 5;
- }
- else if ( strcasecmp(name,"sv") == 0 ) {
- cmpltr = 6;
- }
- else if ( strcasecmp(name,"od") == 0 ) {
- cmpltr = 7;
- }
- else
- cmpltr = -1;
- **s = c;
- }
- if ( cmpltr >= 0 ) {
- while ( **s == ' ' || **s == '\t' )
- *s = *s + 1;
- }
-
- return cmpltr;
- }
-
- int pa_parse_neg_cmpsub_cmpltr(s)
- char **s;
- {
- int cmpltr;
- char *name;
- char c;
-
- cmpltr = -1;
- if ( **s == ',' ) {
- *s+=1;
- name = *s;
- while ( **s != ',' && **s != ' ' && **s != '\t' )
- *s += 1;
- c = **s;
- **s = 0x00;
- if ( strcasecmp(name,"tr") == 0 ) {
- cmpltr = 0;
- }
- else if ( strcmp(name,"<>") == 0 ) {
- cmpltr = 1;
- }
- else if ( strcmp(name,">=") == 0 ) {
- cmpltr = 2;
- }
- else if ( strcmp(name,">") == 0 ) {
- cmpltr = 3;
- }
- else if ( strcmp(name,">>=") == 0 ) {
- cmpltr = 4;
- }
- else if ( strcmp(name,">>") == 0 ) {
- cmpltr = 5;
- }
- else if ( strcasecmp(name,"nsv") == 0 ) {
- cmpltr = 6;
- }
- else if ( strcasecmp(name,"ev") == 0 ) {
- cmpltr = 7;
- }
- **s = c;
- }
- if ( cmpltr >= 0 ) {
- while ( **s == ' ' || **s == '\t' )
- *s = *s + 1;
- }
-
- return cmpltr;
- }
-
- int pa_parse_nonneg_add_cmpltr(s)
- char **s;
- {
- int cmpltr;
- char *name;
- char c;
-
- cmpltr = -1;
- if ( **s == ',' ) {
- *s+=1;
- name = *s;
- while ( **s != ',' && **s != ' ' && **s != '\t' )
- *s += 1;
- c = **s;
- **s = 0x00;
- if ( strcmp(name,"=") == 0 ) {
- cmpltr = 1;
- }
- else if ( strcmp(name,"<") == 0 ) {
- cmpltr = 2;
- }
- else if ( strcmp(name,"<=") == 0 ) {
- cmpltr = 3;
- }
- else if ( strcasecmp(name,"nuv") == 0 ) {
- cmpltr = 4;
- }
- else if ( strcasecmp(name,"znv") == 0 ) {
- cmpltr = 5;
- }
- else if ( strcasecmp(name,"sv") == 0 ) {
- cmpltr = 6;
- }
- else if ( strcasecmp(name,"od") == 0 ) {
- cmpltr = 7;
- }
- **s = c;
- }
- if ( cmpltr >= 0 ) {
- while ( **s == ' ' || **s == '\t' )
- *s = *s + 1;
- }
-
- return cmpltr;
- }
-
- int pa_parse_neg_add_cmpltr(s)
- char **s;
- {
- int cmpltr;
- char *name;
- char c;
-
- cmpltr = -1;
- if ( **s == ',' ) {
- *s+=1;
- name = *s;
- while ( **s != ',' && **s != ' ' && **s != '\t' )
- *s += 1;
- c = **s;
- **s = 0x00;
- if ( strcasecmp(name,"tr") == 0 ) {
- cmpltr = 0;
- }
- else if ( strcmp(name,"<>") == 0 ) {
- cmpltr = 1;
- }
- else if ( strcmp(name,">=") == 0 ) {
- cmpltr = 2;
- }
- else if ( strcmp(name,">") == 0 ) {
- cmpltr = 3;
- }
- else if ( strcmp(name,"uv") == 0 ) {
- cmpltr = 4;
- }
- else if ( strcmp(name,"vnz") == 0 ) {
- cmpltr = 5;
- }
- else if ( strcasecmp(name,"nsv") == 0 ) {
- cmpltr = 6;
- }
- else if ( strcasecmp(name,"ev") == 0 ) {
- cmpltr = 7;
- }
- **s = c;
- }
- if ( cmpltr >= 0 ) {
- while ( **s == ' ' || **s == '\t' )
- *s = *s + 1;
- }
-
- return cmpltr;
- }
-
- void s_seg()
- {
-
- if (strncmp(input_line_pointer, "\"text\"", 6) == 0) {
- input_line_pointer += 6;
- s_text();
- return;
- }
- if (strncmp(input_line_pointer, "\"data\"", 6) == 0) {
- input_line_pointer += 6;
- s_data();
- return;
- }
- if (strncmp(input_line_pointer, "\"data1\"", 7) == 0) {
- input_line_pointer += 7;
- s_data1();
- return;
- }
- as_bad("Unknown segment type");
- demand_empty_rest_of_line();
- return;
- }
-
- void s_private()
- {
- register int temp;
-
- temp = get_absolute_expression ();
- #ifdef OBJ_SOM
- subseg_new (SEG_DATA, (subsegT)temp);
- #else
- subseg_new ("$PRIVATE$", (subsegT)temp);
- #endif
- demand_empty_rest_of_line();
- }
-
- void s_data1()
- {
- #ifdef OBJ_SOM
- subseg_new(SEG_DATA, 1);
- #else
- subseg_new("$PRIVATE$", 1);
- #endif
- demand_empty_rest_of_line();
- return;
- }
-
- void s_proc()
- {
- extern char is_end_of_line[];
-
- while (!is_end_of_line[*input_line_pointer]) {
- ++input_line_pointer;
- }
- ++input_line_pointer;
- return;
- }
-
- void pa_block(z)
- int z;
- {
- register char *p;
- register long int temp_fill;
- register long int temp_size;
- register int i;
-
- temp_size = get_absolute_expression ();
-
- if (z) { /* fill with zeroes even if not requested to do so. */
- temp_fill = 0; /* HP assembler does this too. */
- }
- else {
- temp_fill = 0;
- }
-
- if ( temp_size <= 0 ) {
- as_bad("size < 0, .block ignored");
- temp_size = 0;
- }
- p = frag_var(rs_fill,
- (int)temp_size,
- (int)temp_size,(relax_substateT)0,(symbolS *)0,1,(char *)0);
- bzero (p, (int)temp_size);
-
- /* convert 2 bytes at a time */
-
- for ( i = 0; i < temp_size; i+=2 ) {
- md_number_to_chars (p+i,
- temp_fill,
- (int)( (temp_size - i) > 2 ? 2 : (temp_size - i)));
- }
-
- demand_empty_rest_of_line();
- return;
- }
-
- void pa_call()
- {
-
- pa_call_args(&last_call_desc);
- demand_empty_rest_of_line();
- return;
- }
-
- void pa_call_args(call_desc)
- register call_descS *call_desc;
- {
- register char *name;
- register char c;
- register char *p;
- register int temp;
- register unsigned int arg_reloc;
-
- while ( !is_end_of_statement() ) {
- name = input_line_pointer;
- c = get_symbol_end();
- if ( (strncasecmp(name, "argw", 4) == 0) ) {
- temp = atoi(name+4);
- p = input_line_pointer;
- *p = c;
- input_line_pointer++;
- name = input_line_pointer;
- c = get_symbol_end();
- arg_reloc = pa_build_arg_reloc(name);
- call_desc->arg_reloc |= pa_align_arg_reloc(temp,arg_reloc);
- }
- else if ( (strncasecmp(name, "rtnval", 6) == 0) ) {
- p = input_line_pointer;
- *p = c;
- input_line_pointer++;
- name = input_line_pointer;
- c = get_symbol_end();
- arg_reloc = pa_build_arg_reloc(name);
- call_desc->arg_reloc |= ( arg_reloc & 0x3 );
- }
- else {
- as_bad("Unrecognized .CALL argument: %s",name);
- }
- p = input_line_pointer;
- *p = c;
- if ( !is_end_of_statement() )
- input_line_pointer++;
- }
- }
-
- static int
- is_same_frag(frag1P,frag2P)
- fragS *frag1P;
- fragS *frag2P;
- {
-
- if ( frag1P == NULL )
- return (FALSE);
- else if ( frag2P == NULL )
- return (FALSE);
- else if ( frag1P == frag2P )
- return (TRUE);
- else if ( frag2P->fr_type == rs_fill && frag2P->fr_fix == 0 )
- is_same_frag(frag1P,frag2P->fr_next);
- else
- return (FALSE);
- }
-
- #ifdef OBJ_ELF
- static void
- pa_build_unwind_subspace(call_info)
- call_infoS *call_info;
- {
- char *unwindP;
- asection *seg;
- asection *save_seg;
- subsegT subseg,save_subseg;
- int i;
- char c;
- char *p;
-
- subseg = SUBSEG_UNWIND;
- seg = bfd_get_section_by_name(stdoutput,UNWIND_SECTION_NAME);
- if ( seg == ASEC_NULL ) {
- seg = bfd_make_section_old_way(stdoutput,UNWIND_SECTION_NAME);
- bfd_set_section_flags (stdoutput,
- seg,
- SEC_READONLY | SEC_ALLOC | SEC_LOAD | SEC_RELOC);
- }
-
- /* callinfo.frame is in bytes and unwind_desc is in 8 byte units */
- call_info->ci_unwind.descriptor.frame_size = call_info->frame / 8;
-
- /* Now, dump the unwind descriptor to the $UNWIND$ subspace. This
- creates a couple of relocations */
-
- save_seg = now_seg;
- save_subseg = now_subseg;
- subseg_new((char *)seg->name,subseg);
- unwindP = (char *)&call_info->ci_unwind;
-
- p = frag_more(4);
- call_info->start_offset_frag = frag_now;
- call_info->start_frag_where = p - frag_now->fr_literal;
-
- /* relocation info. for start offset of the function */
-
- fix_new_hppa (frag_now, p - frag_now -> fr_literal, 4,
- call_info->start_symbol, (symbolS *) NULL,
- 0, 0, R_HPPA, e_fsel, 32, 0, (char *) 0);
-
- /** we need to search for the first relocation involving the start_symbol of **/
- /** this call_info descriptor **/
-
- {
- fixS *fixP;
-
- call_info->start_fix = seg_info(now_seg)->fix_root; /* the default */
- for ( fixP = call_info->start_fix; fixP; fixP = fixP->fx_next ) {
- if ( fixP->fx_addsy == call_info->start_symbol
- || fixP->fx_subsy == call_info->start_symbol ) {
- call_info->start_fix = fixP;
- break;
- }
- }
- }
-
- p = frag_more(4);
- call_info->end_offset_frag = frag_now;
- call_info->end_frag_where = p - frag_now->fr_literal;
-
- /* relocation info. for end offset of the function */
-
- fix_new_hppa (frag_now, p - frag_now -> fr_literal, 4,
- call_info->end_symbol, (symbolS *) NULL,
- 0, 0, R_HPPA, e_fsel, 32, 0, (char *) 0);
-
- /** we need to search for the first relocation involving the start_symbol of **/
- /** this call_info descriptor **/
-
- {
- fixS *fixP;
-
- call_info->end_fix = seg_info(now_seg)->fix_root; /* the default */
- for ( fixP = call_info->end_fix; fixP; fixP = fixP->fx_next ) {
- if ( fixP->fx_addsy == call_info->end_symbol
- || fixP->fx_subsy == call_info->end_symbol ) {
- call_info->end_fix = fixP;
- break;
- }
- }
- }
-
- for ( i = 8; i < sizeof(unwind_tableS); i++ ) {
- c = *(unwindP + i);
- {
- FRAG_APPEND_1_CHAR( c );
- }
- }
-
- subseg_new((char *)save_seg->name,save_subseg);
- }
- #else
- #ifdef OBJ_SOM
- static void
- pa_build_unwind_subspace(call_info)
- call_infoS *call_info;
- {
- space_dict_chainS *spaceP;
- subspace_dict_chainS *subspaceP;
- char *unwindP;
- char defined,loadable,code_only,common,dup_common,is_zero,sort;
- int access,space_index,alignment,quadrant;
- segT seg,save_seg;
- subsegT subseg,save_subseg;
- int i;
- char c;
- char *p;
-
- defined = 1;
- loadable = 1;
- code_only = 0;
- common = 0;
- dup_common = 0;
- is_zero = 0;
- sort = 0x40;
- access = 0x2c;
- space_index = 0;
- alignment = 8;
- quadrant = 0;
- subseg = SUBSEG_UNWIND;
- seg = SEG_TEXT;
-
- spaceP = pa_segment_to_space(seg);
-
- if ( (subspaceP = is_defined_subspace("$UNWIND$",SUBSEG_UNWIND) ) ) {
- update_subspace("$UNWIND$",defined,loadable,code_only,common,dup_common,
- sort,is_zero,access,space_index,alignment,quadrant,
- SUBSEG_UNWIND);
- }
- else {
- subspaceP = create_new_subspace(spaceP,"$UNWIND$",defined,loadable,code_only,
- common,dup_common,is_zero,sort,access,
- space_index,alignment,quadrant,seg);
- }
-
-
- /* callinfo.frame is in bytes and unwind_desc is in 8 byte units */
- call_info->ci_unwind.descriptor.frame_size = call_info->frame / 8;
-
- /* Now, dump the unwind descriptor to the $UNWIND$ subspace. This
- creates a couple of relocations */
-
- save_seg = now_seg;
- save_subseg = now_subseg;
- subseg_new(seg,subseg);
- unwindP = (char *)&call_info->ci_unwind;
-
- p = frag_more(4);
- call_info->start_offset_frag = frag_now;
- call_info->start_frag_where = p - frag_now->fr_literal;
-
- /* relocation info. for start offset of the function */
-
- fix_new (frag_now, p - frag_now -> fr_literal, 4,
- call_info->start_symbol, (symbolS *) NULL,
- 0, 0, R_DATA_ONE_SYMBOL, e_fsel, 0, 0, (char *) 0);
-
- /** we need to search for the first relocation involving the start_symbol of **/
- /** this call_info descriptor **/
-
- {
- fixS *fixP;
-
- call_info->start_fix = seg_info(now_seg)->fix_root; /* the default */
- for ( fixP = call_info->start_fix; fixP; fixP = fixP->fx_next ) {
- /*
- if ( ( fixP->fx_addsy == call_info->start_symbol ||
- fixP->fx_subsy == call_info->start_symbol )
- &&
- ( fixP->fx_frag == call_info->start_symbol->sy_frag ) ) {
- */
- if ( ( fixP->fx_addsy == call_info->start_symbol ||
- fixP->fx_subsy == call_info->start_symbol )
- &&
- ( is_same_frag(fixP->fx_frag,call_info->start_symbol->sy_frag) ) ) {
- call_info->start_fix = fixP;
- break;
- }
- }
- }
-
- p = frag_more(4);
- call_info->end_offset_frag = frag_now;
- call_info->end_frag_where = p - frag_now->fr_literal;
-
- /* relocation info. for end offset of the function */
-
- fix_new (frag_now, p - frag_now -> fr_literal, 4,
- call_info->start_symbol, (symbolS *) NULL,
- 0, 0, R_DATA_ONE_SYMBOL, e_fsel, 0, 0, (char *) 0);
-
- /** we need to search for the first relocation involving the start_symbol of **/
- /** this call_info descriptor **/
-
- {
- fixS *fixP;
-
- call_info->end_fix = seg_info(now_seg)->fix_root; /* the default */
- for ( fixP = call_info->end_fix; fixP; fixP = fixP->fx_next ) {
- /*
- if ( ( fixP->fx_addsy == call_info->start_symbol ||
- fixP->fx_subsy == call_info->start_symbol )
- &&
- ( fixP->fx_frag == call_info->start_symbol->sy_frag ) ) {
- */
- if ( ( fixP->fx_addsy == call_info->start_symbol ||
- fixP->fx_subsy == call_info->start_symbol )
- &&
- ( is_same_frag(fixP->fx_frag,call_info->start_symbol->sy_frag) ) ) {
- call_info->end_fix = fixP;
- break;
- }
- }
- }
-
- for ( i = 8; i < sizeof(unwind_tableS); i++ ) {
- c = *(unwindP + i);
- {
- FRAG_APPEND_1_CHAR( c );
- }
- }
-
- subseg_new(save_seg,save_subseg);
-
- }
- #endif
- #endif
-
- void pa_callinfo()
- {
- register char *name;
- register char c;
- register char *p;
- register int temp;
- register symbolS * symbolP;
-
- if ( !within_procedure )
- as_bad(".callinfo is not within a procedure definition");
-
- callinfo_found = TRUE;
-
- while ( !is_end_of_statement() ) {
- name = input_line_pointer;
- c = get_symbol_end();
- if ( (strncasecmp(name, "frame", 5) == 0) ) {
- p = input_line_pointer;
- *p = c;
- input_line_pointer++;
- temp = get_absolute_expression ();
- if ( ( temp & 0x3 ) != 0 ) {
- as_bad("FRAME parameter must be a multiple of 8: %d\n",temp);
- temp = 0;
- }
- last_call_info->frame = temp;
- }
- else if ( (strncasecmp(name, "entry_gr", 8) == 0) ) {
- p = input_line_pointer;
- *p = c;
- input_line_pointer++;
- temp = get_absolute_expression ();
- last_call_info->ci_unwind.descriptor.entry_gr = temp;
- }
- else if ( (strncasecmp(name, "entry_fr", 8) == 0) ) {
- p = input_line_pointer;
- *p = c;
- input_line_pointer++;
- temp = get_absolute_expression ();
- last_call_info->ci_unwind.descriptor.entry_fr = temp;
- }
- else if ( (strncasecmp(name, "entry_sr", 8) == 0) ) {
- p = input_line_pointer;
- *p = c;
- input_line_pointer++;
- temp = get_absolute_expression ();
- last_call_info->entry_sr = temp;
- }
- else if ( (strncasecmp(name, "calls", 5) == 0) ||
- (strncasecmp(name, "caller", 6) == 0) ) {
- p = input_line_pointer;
- *p = c;
- last_call_info->makes_calls = 1;
- }
- else if ( (strncasecmp(name, "no_calls", 8) == 0) ) {
- p = input_line_pointer;
- *p = c;
- last_call_info->makes_calls = 0;
- }
- else if ( (strncasecmp(name, "save_rp",7) == 0) ) {
- p = input_line_pointer;
- *p = c;
- last_call_info->ci_unwind.descriptor.save_rp = 1;
- }
- else if ( (strncasecmp(name, "save_sp",7) == 0) ) {
- p = input_line_pointer;
- *p = c;
- last_call_info->ci_unwind.descriptor.save_sp = 1;
- }
- else if ( (strncasecmp(name, "no_unwind",9) == 0) ) {
- p = input_line_pointer;
- *p = c;
- last_call_info->ci_unwind.descriptor.cannot_unwind = 1;
- }
- else if ( (strncasecmp(name, "hpux_int",7) == 0) ) {
- p = input_line_pointer;
- *p = c;
- last_call_info->hpux_int = 1;
- }
- else {
- as_bad("Unrecognized .CALLINFO argument: %s",name);
- }
- if ( !is_end_of_statement() )
- input_line_pointer++;
- }
-
- demand_empty_rest_of_line();
- return;
- }
-
- void pa_code()
- {
- space_dict_chainS *sdchain;
-
- if ( (sdchain = is_defined_space("$TEXT$")) == NULL ) {
- sdchain = create_new_space(pa_def_spaces[0].name,pa_def_spaces[0].spnum,
- pa_def_spaces[0].loadable,pa_def_spaces[0].defined,
- pa_def_spaces[0].private,pa_def_spaces[0].sort,
- 1,pa_def_spaces[0].segment);
- }
-
- SPACE_DEFINED(sdchain) = 1;
- #ifdef OBJ_SOM
-
- subseg_new (SEG_TEXT, SUBSEG_CODE);
- #else
-
- subseg_new (".text",SUBSEG_CODE);
- #endif
-
- demand_empty_rest_of_line();
- return;
- }
-
- /*
- * This is different than the standard GAS s_comm(). On HP9000/800 machines,
- * the .comm pseudo-op has the following symtax:
- *
- * <label> .comm <length>
- *
- * where <label> is optional and is a symbol whose address will be the start of
- * a block of memory <length> bytes long. <length> must be an absolute expressio
- n.
- * <length> bytes will be allocated in the current space and subspace.
- *
- */
-
- void
- pa_comm()
- {
- register char *p;
- register int size,i;
- register symbolS *symbolP;
- register label_symbolS *label_symbolP = pa_get_label();
-
- if ( label_symbolP )
- symbolP = label_symbolP->lss_label;
- else
- symbolP = NULL;
-
- SKIP_WHITESPACE();
- if ( (size = get_absolute_expression ()) < 0 ) {
- as_warn(".COMMon length (%d.) <0! Ignored.", size);
- ignore_rest_of_line();
- return;
- }
-
- if ( symbolP ) {
- #ifdef OBJ_SOM
- if ( symbolP -> pa_sy_type == ST_STORAGE &&
- symbolP -> pa_sy_scope == SS_UNSAT ) {
- if (symbolP -> pa_sy_value != size) {
- as_warn( "Length of .comm \"%s\" is already %d. Not changed to %d.",
- symbolP -> pa_sy_name, symbolP -> pa_sy_value, size);
- return;
- }
- }
- else {
- symbolP -> pa_sy_value = size;
- symbolP -> pa_sy_scope = SS_UNSAT;
- symbolP -> pa_sy_type = ST_STORAGE;
- symbolP -> sy_ref = sym_def;
- }
- #endif
- #ifdef OBJ_ELF
- if ( S_IS_DEFINED(symbolP) && S_GET_SEGMENT(symbolP) == bss_section ) {
- as_bad("Ignoring attempt to re-define symbol");
- ignore_rest_of_line();
- return;
- }
- if ( S_GET_VALUE(symbolP) ) {
- if ( S_GET_VALUE(symbolP) != size) {
- as_warn( "Length of .comm \"%s\" is already %d. Not changed to %d.",
- S_GET_NAME(symbolP), S_GET_VALUE(symbolP), size);
- return;
- }
- }
- else {
- S_SET_VALUE(symbolP, size);
- S_SET_SEGMENT(symbolP,bss_section);
- S_SET_EXTERNAL(symbolP);
- }
- #endif
- }
-
-
- demand_empty_rest_of_line();
- }
-
- void pa_copyright()
- {
- register char *name;
- register char c;
- register char *p;
- register int temp;
- register symbolS * symbolP;
-
- SKIP_WHITESPACE();
- if (* input_line_pointer == '\"') {
- ++ input_line_pointer; /* -> 1st char of string. */
- name = input_line_pointer;
- while ( (c = next_char_of_string()) >= 0)
- ;
- c = *input_line_pointer;
- *input_line_pointer = '\0';
- *(input_line_pointer-1) = '\0';
- {
- #ifdef OBJ_SOM
- #define PREFIX "Copyright "
- #define MIDFIX ". All rights reserved. No part of this program may be photocopied, reproduced, or transmitted without prior written consent of "
- #define SUFFIX "."
-
- struct aux_hdr_list *aux_hdr_entry;
- int len;
- char *company_name = name;
- char *date_part;
-
- date_part = (char *) index (name,',');
- if ( date_part ) {
- *date_part = 0x00;
- date_part++;
- }
-
- len =
- strlen(PREFIX) +
- strlen(MIDFIX) +
- strlen(SUFFIX) +
- 2*strlen(name);
-
- if ( date_part ) {
- len += strlen(date_part) + strlen(",");
- }
-
- aux_hdr_entry =(struct aux_hdr_list *)malloc(sizeof(struct aux_hdr_list));
- if ( aux_hdr_root ) {
- aux_hdr_entry->ahl_next = aux_hdr_root;
- aux_hdr_root = aux_hdr_entry;
- }
- else {
- aux_hdr_entry->ahl_next = NULL;
- aux_hdr_root = aux_hdr_entry;
- }
- aux_hdr_entry->type = COPYRIGHT_AUX_ID;
- aux_hdr_entry->contents.cpy.header_id.append = 1;
- aux_hdr_entry->contents.cpy.header_id.type = COPYRIGHT_AUX_ID;
- aux_hdr_entry->contents.cpy.header_id.length = len + sizeof(unsigned int);
- while ( aux_hdr_entry->contents.usr_str.header_id.length % 4 )
- aux_hdr_entry->contents.usr_str.header_id.length += 1;
-
- aux_hdr_entry->contents.cpy.string_length = len;
- aux_hdr_entry->contents.cpy.copyright = (char *)(malloc(len + 1));
- strcpy(aux_hdr_entry->contents.cpy.copyright,PREFIX);
- strcat(aux_hdr_entry->contents.cpy.copyright,name);
- if ( date_part ) {
- strcat(aux_hdr_entry->contents.cpy.copyright,",");
- strcat(aux_hdr_entry->contents.cpy.copyright,date_part);
- }
- strcat(aux_hdr_entry->contents.cpy.copyright,MIDFIX);
- strcat(aux_hdr_entry->contents.cpy.copyright,name);
- strcat(aux_hdr_entry->contents.cpy.copyright,SUFFIX);
- aux_hdr_entry->contents.cpy.copyright[len] = NULL;
- #undef PREFIX
- #undef MIDFIX
- #undef SUFFIX
- #endif /* OBJ_SOM */
- }
- *input_line_pointer = c;
- }
- else {
- as_bad( "Expected \"-ed string" );
- }
- demand_empty_rest_of_line();
- }
-
- void pa_end()
- {
-
- demand_empty_rest_of_line();
- return;
- }
-
- void pa_enter()
- {
-
- as_bad(".ENTER encountered. gas doesn't generate entry code sequences.");
- pa_entry();
- return;
- }
-
- void pa_entry()
- {
- char *where;
-
- if ( !within_procedure )
- as_bad("Misplaced .entry. Ignored.");
- else {
- if ( !callinfo_found )
- as_bad("Missing .callinfo.");
-
- last_call_info->start_frag = frag_now;
- }
- demand_empty_rest_of_line();
- within_entry_exit = TRUE;
- where = frag_more(0);
- #ifdef OBJ_SOM
- fix_new (frag_now, where - frag_now->fr_literal, 0,
- last_call_info->start_symbol, (symbolS *) NULL, 0, 0,
- R_ENTRY, e_fsel, 0, 0, (char *) &last_call_info->ci_unwind.descriptor);
- #else
- #ifdef OBJ_ELF
- /* XXX: no ENTRY relocation for PA ELF. What do we do instead? */
- #else
- fix_new_hppa (frag_now, where - frag_now->fr_literal, 0,
- last_call_info->start_symbol, (symbolS *) NULL, 0, 0,
- R_HPPA_ENTRY, 0, 0, 0,
- (char *) &last_call_info->ci_unwind.descriptor);
- #endif
- #endif
- return;
- }
-
- void pa_equ(reg)
- int reg;
- {
- register label_symbolS *label_symbolP = pa_get_label();
- register symbolS * symbolP;
-
- if ( label_symbolP ) {
- symbolP = label_symbolP->lss_label;
- #ifdef OBJ_SOM
- symbolP->pa_sy_value = get_absolute_expression();
- symbolP->pa_sy_type = ST_ABSOLUTE;
- symbolP->sy_ref = sym_unref;
- symbolP->sy_equ = 1;
- #else
- S_SET_VALUE(symbolP,get_absolute_expression());
- S_SET_SEGMENT(symbolP,&bfd_abs_section);
- #endif
- }
- else {
- if ( reg )
- as_bad(".REG must use a label");
- else
- as_bad(".EQU must use a label");
- }
-
- demand_empty_rest_of_line();
- return;
- }
-
- void process_exit()
- {
- char *where;
-
- where = frag_more(0);
- #ifdef OBJ_SOM
- fix_new (frag_now, where - frag_now->fr_literal, 0,
- last_call_info->start_symbol, (symbolS *) NULL, 0,
- 0, R_EXIT, e_fsel, 0, 0, (char *) NULL);
- #endif
- #ifdef OBJ_ELF
- /* XXX: no EXIT relocation for PA ELF. All we do is create a */
- /* temporary symbol marking the end of the function. */
- {
- char *name = (char *)xmalloc(strlen("L\001end_") +
- strlen(S_GET_NAME(last_call_info->start_symbol)) + 1);
-
- if ( name ) {
- symbolS *symbolP;
-
- strcpy(name,"L\001end_");
- strcat(name,S_GET_NAME(last_call_info->start_symbol));
-
- symbolP = symbol_find (name);
- if ( symbolP )
- as_warn("Symbol '%s' already defined.", name);
- else {
- /* symbol value should be the offset of the */
- /* last instruction of the function */
- symbolP = symbol_new(name,
- now_seg,
- (valueT)(obstack_next_free(&frags)-frag_now->fr_literal-4),
- frag_now);
-
- assert(symbolP);
-
- symbolP->bsym->flags = last_call_info->start_symbol->bsym->flags;
- symbol_table_insert(symbolP);
- }
- if ( symbolP )
- last_call_info->end_symbol = symbolP;
- else
- as_bad("Symbol '%s' could not be created.", name);
-
- }
- else
- as_bad("No memory for symbol name.");
- }
- #else
- fix_new_hppa (frag_now, where - frag_now->fr_literal, 0,
- last_call_info->start_symbol, (symbolS *) NULL, 0,
- 0, R_HPPA_EXIT, 0, 0, 0, (char *) NULL);
- #endif
- last_call_info->end_frag = frag_now;
-
- pa_build_unwind_subspace(last_call_info);
-
- exit_processing_complete = TRUE;
- }
-
- void pa_exit()
- {
-
- if ( !within_procedure )
- as_bad(".EXIT must appear within a procedure");
- else {
- if ( !callinfo_found )
- as_bad("Missing .callinfo");
- else {
- if ( !within_entry_exit )
- as_bad("No .ENTRY for this .EXIT");
- else {
- within_entry_exit = FALSE;
- process_exit();
- }
- }
- }
- demand_empty_rest_of_line();
- return;
- }
-
- void pa_export()
- {
- register char *name;
- register char c;
- register char *p;
- register int temp;
- register int regno;
- register symbolS * symbolP;
-
- name = input_line_pointer;
- c = get_symbol_end();
- /* just after name is now '\0' */
-
- if ( (symbolP = symbol_find_or_make(name)) == NULL ) {
- as_bad("Cannot define export symbol: %s\n",name);
- p = input_line_pointer;
- *p = c;
- input_line_pointer++;
- }
- else {
- #ifdef OBJ_SOM
- symbolP->pa_sy_dict.symbol_scope = SS_UNIVERSAL;
- /* determination of the symbol_type field will have to wait until
- we know the subspace index (within the object file) of the subspace
- containing this symbol */
- #else
- /* S_SET_SEGMENT(symbolP,&bfd_und_section); */
- S_SET_EXTERNAL(symbolP);
- /* symbolP->sy_frag = frag_now; */
- #endif
-
- p = input_line_pointer;
- *p = c;
- if ( !is_end_of_statement() ) {
- input_line_pointer++;
- pa_export_args(symbolP);
- }
- }
-
- demand_empty_rest_of_line();
- return;
- }
-
- void pa_export_args(symbolP)
- register symbolS *symbolP;
- {
- register char *name;
- register char c;
- register char *p;
- register int temp;
-
- if (strncasecmp(input_line_pointer, "absolute", 8) == 0) {
- input_line_pointer += 8;
- #ifdef OBJ_SOM
- symbolP->pa_sy_dict.symbol_type = ST_ABSOLUTE;
- #else
- S_SET_SEGMENT(symbolP,&bfd_abs_section);
- #endif
- }
- else if (strncasecmp(input_line_pointer, "code", 4) == 0) {
- input_line_pointer += 4;
- #ifdef OBJ_SOM
- symbolP->pa_sy_dict.symbol_type = ST_CODE;
- #else
- /* S_SET_SEGMENT(symbolP,text_section); */
- #endif
- }
- else if (strncasecmp(input_line_pointer, "data", 4) == 0) {
- input_line_pointer += 4;
- #ifdef OBJ_SOM
- symbolP->pa_sy_dict.symbol_type = ST_DATA;
- #else
- /* S_SET_SEGMENT(symbolP,data_section); */
- #endif
- }
- else if ( (strncasecmp(input_line_pointer, "entry", 5) == 0) ) {
- input_line_pointer += 5;
- #ifdef OBJ_SOM
- symbolP->pa_sy_dict.symbol_type = ST_ENTRY;
- #else
- symbolP->bsym->flags |= BSF_FUNCTION;
- #endif
- }
- else if (strncasecmp(input_line_pointer, "millicode", 9) == 0) {
- input_line_pointer += 9;
- #ifdef OBJ_SOM
- symbolP->pa_sy_dict.symbol_type = ST_MILLICODE;
- #endif
- }
- else if (strncasecmp(input_line_pointer, "plabel", 6) == 0) {
- input_line_pointer += 6;
- #ifdef OBJ_SOM
- symbolP->pa_sy_dict.symbol_type = ST_PLABEL;
- #endif
- }
- else if (strncasecmp(input_line_pointer, "pri_prog", 8) == 0) {
- input_line_pointer += 8;
- #ifdef OBJ_SOM
- symbolP->pa_sy_dict.symbol_type = ST_PRI_PROG;
- #endif
- }
- else if (strncasecmp(input_line_pointer, "sec_prog", 8) == 0) {
- input_line_pointer += 8;
- #ifdef OBJ_SOM
- symbolP->pa_sy_dict.symbol_type = ST_SEC_PROG;
- #endif
- }
-
- while ( !is_end_of_statement() ) {
- if ( *input_line_pointer == ',' )
- input_line_pointer++;
- name = input_line_pointer;
- c = get_symbol_end();
- if ( (strncasecmp(name, "argw", 4) == 0) ) {
- p = input_line_pointer;
- *p = c;
- input_line_pointer++;
- temp = atoi(name+4);
- name = input_line_pointer;
- c = get_symbol_end();
- #ifdef OBJ_SOM
- symbolP->pa_sy_dict.arg_reloc |=
- pa_align_arg_reloc(temp,pa_build_arg_reloc(name));
- #endif
- *input_line_pointer = c;
- }
- else if (( strncasecmp(name, "rtnval",6)) == 0 ) {
- p = input_line_pointer;
- *p = c;
- input_line_pointer++;
- name = input_line_pointer;
- c = get_symbol_end();
- #ifdef OBJ_SOM
- symbolP->pa_sy_dict.arg_reloc |= pa_build_arg_reloc(name);
- #endif
- *input_line_pointer = c;
- }
- else if (( strncasecmp(name, "priv_lev",8)) == 0 ) {
- p = input_line_pointer;
- *p = c;
- input_line_pointer++;
- /*** temp = get_absolute_expression (); ***/
- temp = atoi(input_line_pointer);
- c = get_symbol_end();
- *input_line_pointer = c;
- #ifdef OBJ_SOM
- symbolP->sy_priv_lev = temp & 3; /* this is stored in symbol_value later */
- #endif
- }
- else {
- as_bad("Undefined .EXPORT/.IMPORT argument (ignored): %s",name);
- p = input_line_pointer;
- *p = c;
- }
- if ( !is_end_of_statement() )
- input_line_pointer++;
- }
- }
-
- void pa_import()
- {
- register char *name;
- register char c;
- register char *p;
- register symbolS *symbolP;
- register expressionS resultP; /* Deliver result here. */
-
- name = input_line_pointer;
- c = get_symbol_end();
- /* just after name is now '\0' */
-
- symbolP = symbol_find_or_make (name);
- #if defined(OBJ_ELF)
- /* symbolP->bsym->flags |= BSF_IMPORT; */ /* XXX BSF_IMPORT is obsolete */
- #else
- /* Check to see if this symbol has already been exported (this means its */
- /* defined locally and the import statement is redundant). */
- /* If it has not been exported, go ahead and mark this symbol as SS_UNSAT */
- /* (an unsatisfied external symbol) */
-
- /* But, if the symbol has already been referenced (sy_ref == TRUE),
- leave it alone. */
-
- if ( !symbolP->sy_ref ) {
- if ( symbolP->pa_sy_dict.symbol_scope != SS_UNIVERSAL ) {
- symbolP->pa_sy_dict.symbol_scope = SS_UNSAT;
- symbolP->sy_ref = FALSE;
- }
- }
- #endif
-
- p = input_line_pointer;
- *p = c;
-
- if ( !is_end_of_statement() ) {
- input_line_pointer++;
-
- pa_export_args(symbolP);
- #ifdef OBJ_ELF
- /* In ELF, since this is an import, leave the section undefined. */
- /* S_SET_SEGMENT(symbolP,&bfd_und_section); */
- #endif
- }
- else {
- #ifdef OBJ_SOM
- /* no further arguments, assign a default type according
- to the current subspace (CODE or DATA) */
- switch (now_seg) {
- case SEG_TEXT: symbolP->pa_sy_dict.symbol_type = ST_CODE;break;
- case SEG_ABSOLUTE: symbolP->pa_sy_dict.symbol_type = ST_ABSOLUTE;break;
- default: symbolP->pa_sy_dict.symbol_type = ST_DATA;
- }
- #else
- /* In ELF, if the section is undefined, then the symbol is undefined */
- /* Since this is an import, leave the section undefined. */
- S_SET_SEGMENT(symbolP,&bfd_und_section);
- #endif
- }
-
-
- demand_empty_rest_of_line();
- return;
- }
-
- void pa_label()
- {
- register char *name;
- register char c;
- register char *p;
-
- name = input_line_pointer;
- c = get_symbol_end();
- /* just after name is now '\0' */
-
- if ( strlen(name) > 0 ) {
- colon(name);
- p = input_line_pointer;
- *p = c;
- }
- else {
- as_warn("Missing label name on .LABEL");
- }
-
- if ( !is_end_of_statement() ) {
- as_warn("extra .LABEL arguments ignored.");
- ignore_rest_of_line();
- }
- demand_empty_rest_of_line();
- return;
- }
-
- void pa_leave()
- {
-
- as_bad(".LEAVE encountered. gas doesn't generate exit code sequences.");
- pa_exit();
- return;
- }
-
- void pa_origin()
- {
- s_org(); /* ORG actually allows another argument (the fill value)
- but maybe this is OK? */
- return;
- }
-
- void pa_proc()
- {
- call_infoS *call_info;
-
- if ( within_procedure )
- as_fatal("Nested procedures");
-
- callinfo_found = FALSE;
- within_procedure = TRUE;
- exit_processing_complete = FALSE;
-
- /* create another call_info structure */
-
- call_info = (call_infoS *)xmalloc(sizeof(call_infoS));
-
- if ( !call_info )
- as_fatal("Cannot allocate unwind descriptor\n");
-
- bzero(call_info,sizeof(call_infoS));
-
- call_info->ci_next = NULL;
-
- if ( call_info_root == NULL ) {
- call_info_root = call_info;
- last_call_info = call_info;
- }
- else {
- last_call_info->ci_next = call_info;
- last_call_info = call_info;
- }
-
- /* set up defaults on call_info structure */
-
- call_info->ci_unwind.descriptor.cannot_unwind = 1; /* PJH: Tim says gcc code
- is unwindable */
- call_info->ci_unwind.descriptor.region_desc = 1;
- call_info->entry_sr = ~0;
- call_info->makes_calls = 1;
- call_info->hpux_int = 0;
-
- /* If we got a .PROC pseudo-op, we know that the function is defined
- locally. Make sure it gets into the symbol table */
- {
- label_symbolS *label_symbolP = pa_get_label();
-
- if ( label_symbolP ) {
- if ( label_symbolP->lss_label ) {
- #ifdef OBJ_SOM
- label_symbolP->lss_label->sy_ref |= sym_def;
- #endif
- last_call_info->start_symbol = label_symbolP->lss_label;
- label_symbolP->lss_label->bsym->flags |= BSF_FUNCTION;
- }
- else
- as_bad("Missing function name for .PROC (corrupted label)");
- }
- else
- as_bad("Missing function name for .PROC");
- }
-
- demand_empty_rest_of_line();
- return;
- }
-
- void pa_procend()
- {
-
- if ( !within_procedure )
- as_bad("misplaced .procend");
-
- if ( !callinfo_found )
- as_bad("Missing .callinfo for this procedure");
-
- if ( within_entry_exit )
- as_bad("Missing .EXIT for a .ENTRY");
-
- if ( !exit_processing_complete )
- process_exit();
-
- within_procedure = FALSE;
- demand_empty_rest_of_line();
- return;
- }
-
- space_dict_chainS *pa_parse_space_stmt(space_name,create_flag)
- char *space_name;
- int create_flag;
- {
- register char *name;
- register char c;
- register char *p;
- register int temp;
-
- char *ptemp;
- int spnum;
- char loadable;
- char defined;
- char private;
- char sort;
- #ifdef OBJ_SOM
- segT seg;
- #else
- asection * seg;
- #endif
- space_dict_chainS *space;
-
- /* load default values */
- spnum = 0;
- loadable = TRUE;
- defined = TRUE;
- private = FALSE;
- if ( strcasecmp(space_name,"$TEXT$") == 0 ) {
- #ifdef OBJ_SOM
- seg = SEG_TEXT;
- #else
- seg = text_section;
- #endif
- sort = 8;
- }
- else {
- #ifdef OBJ_SOM
- seg = SEG_DATA;
- #else
- seg = data_section;
- #endif
- sort = 16;
- }
-
- if ( !is_end_of_statement() ) {
- print_errors = FALSE;
- ptemp = input_line_pointer + 1;
- if ( (temp = pa_parse_number(&ptemp)) >= 0 ) {
- spnum = temp;
- input_line_pointer = ptemp;
- }
- else {
- while ( !is_end_of_statement() ) {
- input_line_pointer++;
- name = input_line_pointer;
- c = get_symbol_end();
- if ( (strncasecmp(name, "SPNUM", 5) == 0) ) {
- p = input_line_pointer;
- *p = c;
- input_line_pointer++;
- temp = get_absolute_expression ();
- spnum = temp;
- }
- else if ( (strncasecmp(name, "SORT",4) == 0) ) {
- p = input_line_pointer;
- *p = c;
- input_line_pointer++;
- temp = get_absolute_expression ();
- sort = temp;
- }
- else if ( (strncasecmp(name, "UNLOADABLE",10) == 0) ) {
- p = input_line_pointer;
- *p = c;
- loadable = FALSE;
- }
- else if ( (strncasecmp(name, "NOTDEFINED",10) == 0) ) {
- p = input_line_pointer;
- *p = c;
- defined = FALSE;
- }
- else if ( (strncasecmp(name, "PRIVATE",7) == 0) ) {
- p = input_line_pointer;
- *p = c;
- private = TRUE;
- }
- else {
- as_bad("Unrecognized .SPACE argument");
- p = input_line_pointer;
- *p = c;
- }
- }
- }
- print_errors = TRUE;
- }
- if ( create_flag )
- space = create_new_space(space_name,spnum,loadable,defined,private,sort,1,seg);
- else { /* if no creation of new space, this must be the first */
- /* occurrence of a built-in space */
- space = is_defined_space(space_name);
- SPACE_SPNUM(space) = spnum;
- SPACE_LOADABLE(space) = loadable & 1;
- SPACE_DEFINED(space) = defined & 1;
- SPACE_PRIVATE(space) = private & 1;
- SPACE_SORT(space) = sort & 0xff;
- space->sd_defined = 1;
- space->sd_seg = seg;
- }
- return space;
- }
-
- void pa_align_subseg(seg,subseg)
- #ifdef OBJ_SOM
- segT seg;
- #else
- asection * seg;
- #endif
- subsegT subseg;
- {
- subspace_dict_chainS * now_subspace;
- int alignment;
- int shift;
-
- now_subspace = pa_subsegment_to_subspace(seg,subseg);
- if ( SUBSPACE_ALIGN(now_subspace) == 0 )
- alignment = now_subspace->ssd_last_align;
- else if ( now_subspace->ssd_last_align > SUBSPACE_ALIGN(now_subspace) )
- alignment = now_subspace->ssd_last_align;
- else
- alignment = SUBSPACE_ALIGN(now_subspace);
-
- shift = 0;
- while ( (1 << shift) < alignment )
- shift++;
-
- frag_align(shift,0);
- }
-
- void pa_space()
- {
- register char *name;
- register char c;
- register char *p;
- register int temp;
- register symbolS * symbolP;
- register space_dict_chainS *sd_chain;
- char space_name[40];
-
- if ( within_procedure ) {
- as_bad("Can\'t change spaces within a procedure definition. Ignored");
- ignore_rest_of_line();
- }
- else {
- if (strncasecmp(input_line_pointer, "$text$", 6) == 0) {
- input_line_pointer += 6;
- sd_chain = is_defined_space("$TEXT$");
- if ( sd_chain == NULL )
- sd_chain = pa_parse_space_stmt("$TEXT$",1);
- else if ( sd_chain->sd_defined == 0 )
- sd_chain = pa_parse_space_stmt("$TEXT$",0);
-
- current_space = sd_chain;
- SPACE_DEFINED(current_space) = 1;
- current_space->sd_defined = 1;
- #ifdef OBJ_SOM
- if ( now_seg != SEG_TEXT ) /* no need to align if we are already there */
- #else
- if ( now_seg != text_section )/* no need to align if we are already there */
- #endif
- pa_align_subseg(now_seg,now_subseg);
-
- #ifdef OBJ_SOM
- subseg_new (SEG_TEXT, sd_chain->sd_last_subseg);
- current_subspace = pa_subsegment_to_subspace(SEG_TEXT,
- sd_chain->sd_last_subseg);
- #else
- subseg_new ((char *)text_section->name, sd_chain->sd_last_subseg);
- current_subspace = pa_subsegment_to_subspace(text_section,
- sd_chain->sd_last_subseg);
- #endif
- demand_empty_rest_of_line();
- return;
- }
- if (strncasecmp(input_line_pointer, "$private$", 9) == 0) {
- input_line_pointer += 9;
- sd_chain = is_defined_space("$PRIVATE$");
- if ( sd_chain == NULL )
- sd_chain = pa_parse_space_stmt("$PRIVATE$",1);
- else if ( sd_chain->sd_defined == 0 )
- sd_chain = pa_parse_space_stmt("$PRIVATE$",0);
-
- current_space = sd_chain;
- SPACE_DEFINED(current_space) = 1;
- current_space->sd_defined = 1;
- #ifdef OBJ_SOM
- if ( now_seg != SEG_DATA ) /* no need to align if we are already there */
- #else
- if ( now_seg != data_section )/* no need to align if we are already there */
- #endif
- pa_align_subseg(now_seg,now_subseg);
- #ifdef OBJ_SOM
- subseg_new (SEG_DATA, sd_chain->sd_last_subseg);
- current_subspace = pa_subsegment_to_subspace(SEG_DATA,
- sd_chain->sd_last_subseg);
- #else
- subseg_new ((char *)data_section->name, sd_chain->sd_last_subseg);
- current_subspace = pa_subsegment_to_subspace(data_section,
- sd_chain->sd_last_subseg);
- #endif
- demand_empty_rest_of_line();
- return;
- }
- if (strncasecmp(input_line_pointer,
- GDB_DEBUG_SPACE_NAME,strlen(GDB_DEBUG_SPACE_NAME)) == 0) {
- input_line_pointer += strlen(GDB_DEBUG_SPACE_NAME);
- sd_chain = is_defined_space(GDB_DEBUG_SPACE_NAME);
- if ( sd_chain == NULL )
- sd_chain = pa_parse_space_stmt(GDB_DEBUG_SPACE_NAME,1);
- else if ( sd_chain->sd_defined == 0 )
- sd_chain = pa_parse_space_stmt(GDB_DEBUG_SPACE_NAME,0);
-
- current_space = sd_chain;
- SPACE_DEFINED(current_space) = 1;
- current_space->sd_defined = 1;
- #ifdef OBJ_SOM
- if ( now_seg != SEG_GDB ) /* no need to align if we are already there */
- pa_align_subseg(now_seg,now_subseg);
- subseg_new (SEG_GDB, sd_chain->sd_last_subseg);
- current_subspace = pa_subsegment_to_subspace(SEG_GDB,
- sd_chain->sd_last_subseg);
- #else
- if ( now_seg != gdb_section ) /* no need to align if we are already there */
- pa_align_subseg(now_seg,now_subseg);
- subseg_new ((char *)gdb_section->name, sd_chain->sd_last_subseg);
- current_subspace = pa_subsegment_to_subspace(gdb_section,
- sd_chain->sd_last_subseg);
- #endif
- demand_empty_rest_of_line();
- return;
- }
-
- /* it could be a space specified by number */
-
- if ( (temp = pa_parse_number(&input_line_pointer)) >= 0 ) {
- if ( sd_chain = pa_find_space_by_number(temp) ) {
- current_space = sd_chain;
- SPACE_DEFINED(current_space) = 1;
- current_space->sd_defined = 1;
- if ( now_seg != sd_chain->sd_seg ) /* don't align if we're already there */
- pa_align_subseg(now_seg,now_subseg);
- #ifdef OBJ_SOM
- subseg_new (sd_chain->sd_seg, sd_chain->sd_last_subseg);
- #else
- subseg_new ((char *)sd_chain->sd_seg->name, sd_chain->sd_last_subseg);
- #endif
- current_subspace = pa_subsegment_to_subspace(sd_chain->sd_seg,
- sd_chain->sd_last_subseg);
- demand_empty_rest_of_line();
- return;
- }
- }
-
- /* not a number, attempt to create a new space */
-
- name = input_line_pointer;
- c = get_symbol_end();
- space_name[0] = 0x00;
- strcpy(space_name,name);
- *input_line_pointer = c;
-
- sd_chain = pa_parse_space_stmt(space_name,1);
- current_space = sd_chain;
- SPACE_DEFINED(current_space) = 1;
- current_space->sd_defined = 1;
- if ( now_seg != sd_chain->sd_seg ) /* don't align if we're already there */
- pa_align_subseg(now_seg,now_subseg);
- #ifdef OBJ_SOM
- subseg_new (sd_chain->sd_seg, sd_chain->sd_last_subseg);
- #else
- subseg_new ((char *)sd_chain->sd_seg->name, sd_chain->sd_last_subseg);
- #endif
- current_subspace = pa_subsegment_to_subspace(sd_chain->sd_seg,
- sd_chain->sd_last_subseg);
- demand_empty_rest_of_line();
- }
- return;
- }
-
- void pa_spnum()
- {
- register char *name;
- register char c;
- register char *p;
- space_dict_chainS *space;
-
- name = input_line_pointer;
- c = get_symbol_end();
- space = is_defined_space(name);
- if ( space ) {
- p = frag_more (4);
- /* put bytes in right order. */
- md_number_to_chars (p,SPACE_SPNUM(space),4);
- }
- else
- as_warn("Undefined space: '%s' Assuming space number = 0.",name);
-
- *input_line_pointer = c;
- demand_empty_rest_of_line();
- return;
- }
-
- static
- int is_power_of_2(value)
- int value;
- {
- int shift;
-
- shift = 0;
- while ( ( 1 << shift ) != value && shift < 32 )
- shift++;
-
- if ( shift >= 32 )
- shift = 0;
- return shift;
- }
-
- void pa_subspace()
- {
- register char *name;
- register char c;
- register char *p;
- register int temp;
- register symbolS * symbolP;
-
- char loadable,code_only,common,dup_common,zero;
- char sort;
- int number;
- int i;
- int access;
- int space_index;
- int alignment;
- int quadrant;
- int subseg;
- space_dict_chainS *space;
- subspace_dict_chainS *ssd;
- subspace_dict_chainS *ssdCh;
- char *ss_name;
- int is_power_of_2();
-
- if ( within_procedure ) {
- as_bad("Can\'t change subspaces within a procedure definition. Ignored");
- ignore_rest_of_line();
- }
- else {
- name = input_line_pointer;
- c = get_symbol_end();
- space = pa_segment_to_space(now_seg);
- ssd = is_defined_subspace(name,space->sd_last_subseg);
-
- ss_name = xmalloc(strlen(name)+1);
- strcpy(ss_name,name);
-
- *input_line_pointer = c;
-
- /* load default values */
- sort = 0;
- access = 0x7f;
- loadable = 1;
- common = 0;
- dup_common = 0;
- code_only = 0;
- zero = 0;
- space_index = ~0; /* filled in when the .o file is written */
- alignment = 0; /* alignment=0 means no ALIGN= appeared on the .SUBSPA */
- /* pseudo-op. The default will be the largest .ALIGN */
- /* encountered (or 1 if no .ALIGN is encountered) */
- quadrant = 0;
-
- if ( ssd ) {
- if ( ssd->ssd_defined ) {
- #ifdef OBJ_SOM
- subseg_new(now_seg,ssd->ssd_subseg);
- #else
- /* subseg_new(now_seg->name,ssd->ssd_subseg); */
- subseg_new((char *)ssd->ssd_seg->name,ssd->ssd_subseg);
- #endif
- if ( !is_end_of_statement() ) {
- as_warn("Parameters of an existing subspace can\'t be modified");
- }
- demand_empty_rest_of_line();
- return;
- }
- else {
- ssd->ssd_defined = 1;
- }
- }
- else {
- /* a new subspace */
- /* load default values */
- i = 0;
- while ( pa_def_subspaces[i].name ) {
- if ( strcasecmp(pa_def_subspaces[i].name,ss_name) == 0 ) {
- loadable = pa_def_subspaces[i].loadable;
- common = pa_def_subspaces[i].common;
- dup_common = pa_def_subspaces[i].dup_common;
- code_only = pa_def_subspaces[i].code_only;
- zero = pa_def_subspaces[i].zero;
- space_index = pa_def_subspaces[i].space_index;
- /* alignment = pa_def_subspaces[i].alignment; */
- alignment = 0;
- quadrant = pa_def_subspaces[i].quadrant;
- access = pa_def_subspaces[i].access;
- sort = pa_def_subspaces[i].sort;
- break;
- }
- i++;
- }
- }
-
- if ( !is_end_of_statement() ) {
- input_line_pointer++;
- while ( !is_end_of_statement() ) {
- name = input_line_pointer;
- c = get_symbol_end();
- if ( (strncasecmp(name, "QUAD", 4) == 0) ) {
- *input_line_pointer = c;
- input_line_pointer++;
- temp = get_absolute_expression ();
- quadrant = temp;
- }
- else if ( (strncasecmp(name, "ALIGN", 5) == 0) ) {
- *input_line_pointer = c;
- input_line_pointer++;
- temp = get_absolute_expression ();
- alignment = temp;
- if ( !is_power_of_2(alignment) ) {
- as_bad("Alignment must be a power of 2");
- alignment = 1;
- }
- }
- else if ( (strncasecmp(name, "ACCESS",6) == 0) ) {
- *input_line_pointer = c;
- input_line_pointer++;
- temp = get_absolute_expression ();
- access = temp;
- }
- else if ( (strncasecmp(name, "SORT",4) == 0) ) {
- *input_line_pointer = c;
- input_line_pointer++;
- temp = get_absolute_expression ();
- sort = temp;
- }
- else if ( (strncasecmp(name, "CODE_ONLY",9) == 0) ) {
- *input_line_pointer = c;
- code_only = 1;
- }
- else if ( (strncasecmp(name, "UNLOADABLE",10) == 0) ) {
- *input_line_pointer = c;
- loadable = 0;
- }
- else if ( (strncasecmp(name, "COMMON",6) == 0) ) {
- *input_line_pointer = c;
- common = 1;
- }
- else if ( (strncasecmp(name, "DUP_COMM",8) == 0) ) {
- *input_line_pointer = c;
- dup_common = 1;
- }
- else if ( (strncasecmp(name, "ZERO",4) == 0) ) {
- *input_line_pointer = c;
- zero = 1;
- }
- else {
- as_bad("Unrecognized .SUBSPACE argument");
- }
- if ( !is_end_of_statement() )
- input_line_pointer++;
- }
- }
- space = pa_segment_to_space(now_seg);
- if ( ssd ) {
- current_subspace = update_subspace(ss_name,1,loadable,code_only,
- common,dup_common,sort,zero,access,
- space_index,alignment,quadrant,
- ssd->ssd_subseg);
- }
- else {
- current_subspace = create_new_subspace(space,ss_name,1,loadable,code_only,
- common,dup_common,zero,sort,
- access,space_index,alignment,
- quadrant,now_seg);
- }
- SUBSPACE_SUBSPACE_START(current_subspace) = pa_subspace_start(space,quadrant);
-
- demand_empty_rest_of_line();
- #ifdef OBJ_SOM
- subseg_new (current_subspace->ssd_seg, current_subspace->ssd_subseg);
- #else
- subseg_new ((char *)current_subspace->ssd_seg->name, current_subspace->ssd_subseg);
- #endif
- }
- return;
- }
-
- /* For ELF, this function serves one purpose: to setup the st_size */
- /* field of STT_FUNC symbols. To do this, we need to scan the */
- /* call_info structure list, determining st_size in one of two possible */
- /* ways: */
-
- /* 1. call_info->start_frag->fr_fix has the size of the fragment. */
- /* This approach assumes that the function was built into a */
- /* single fragment. This works for most cases, but might fail. */
- /* For example, if there was a segment change in the middle of */
- /* the function. */
-
- /* 2. The st_size field is the difference in the addresses of the */
- /* call_info->start_frag->fr_address field and the fr_address */
- /* field of the next fragment with fr_type == rs_fill and */
- /* fr_fix != 0. */
-
- void tc_final_processing_hook()
- {
- extern call_infoS *call_info_root;
-
- call_infoS *ciP;
-
- for ( ciP = call_info_root; ciP; ciP = ciP->ci_next ) {
- elf_symbol_type *esym = (elf_symbol_type *)ciP->start_symbol->bsym;
- esym->internal_elf_sym.st_size =
- ciP->end_symbol->bsym->value
- - ciP->start_symbol->bsym->value + 4;
- }
- }
-